偿还技术债 - 经过重构拯救老代码(翻译)

###偿还技术债 - 经过重构拯救老代码程序员

**尝试去接管一个陈旧的代码库使他成为达成一个可控的状态?**这几年的大型的旧web应用程序开发给了咱们以下这些建议。web

####经过重构去拯救旧代码 松鼠会由于忘记本身把松果放在那里,使得每一年多了几千棵松树。相似的,这些事情在项目中都没有什么关系。你的项目是能够被拯救的数据库

**不管代码多么的杂乱,让人疯狂。**可是你的老板让你上了,你要相信无论前路多么曲折坎坷,你总能搞定的!安全

####心无畏惧框架

公平的说。比起冲进一个四处鲜血还有巨龙守在门口的沼泽地待几年,你更愿意在一片清新的草原上散步。模块化

不幸的是,你的老板和这片沼泽地的公爵达成了一个协议,派你上了。函数

无论怎么样,你上了,所要作的就是把这块泥泞的沼泽变成一块美丽的牧场工具

####技术债 - 它怎么会这样 当你在项目中遇到一个又一个坑的时候,你可能在想:这是哪一个“无能”的人作的?有人确定能预见这个问题,可是为何不是这样呢。单元测试

可能吧,不过更多的时候并非这样。包括咱们本身,很自信的写出的东西可能以后本身也不知道是什么了。测试

“无能”这个词并不适合解释这种状况。从工做自己的角度解释,它应该叫作“技术债”。

####代码癌

“代码癌”这个东西充斥在各个项目的开发周期内,指的是为了快速解决当下问题采起的临时方案(原文中为“Ugly hacks”)。随着这种只完成了功能可是很难维护的东西的出现,而后技术债就开始越积越多。

而后,一点一点的,项目就开始失控。不经手真正代码的的人根本不会在乎这一点,可是,最终,他可能最后落在你的手上。

对于任何项目来讲,快速完成需求,推出新的功能都是很是重要的。若是作不到,珍贵的用户就会离开。举个例子,就像是他们宁愿去隔壁泥泞沼泽上的酒吧喝着长岛冰茶,也不会在你花了一全年修剪工整的草坪上傻站着。

因此,就算是一个健康的项目,技术债也必定会产生,可是为了不代码最终变得没法维护,这种积累的技术债在某些时候必定要解决的。

为了不让一群疯狂的受害者冲进你的沼泽地找你讨债。做为沼泽地的主人,你可能须要一些**“重构”**:交换一些代码的位置,让他可以更好地维护和拓展。

####说服客户

对于这片泥沼的公爵,你须要告诉他他的土地上正在不断的进入小怪物。由于总有客户想要这样那样的功能。当你面对一个deadline定为一周可是你完成它至少要两周的需求,你须要学会向他解释,让他明白你须要花一点时间来作点小小的重构

若是作不到这一点,能够预见,技术债将不断增长,最后没法收场。

其实你的目的和你的客户是一致的,愉快而顺利的工做,而后你们都能赚钱~ 这个的前提就是须要有一个稳定的项目可让你从容的写出你的代码。

####争取你的自由

你须要学会如何将状况解释清楚。我以为最好的办法就是向这片泥沼的主人解释清楚有哪些潜在的风险隐藏在角落里,要让他知道你的好意。你能够试试下面几条建议:

1.解释什么叫作“技术债”,告诉这种债务太高会让开发愈来愈慢。咱们可能须要花费不少时间才能找到问题,并且要花费不少时间去解决它。

2.给出清晰的短时间目标和计划,告诉客户你能够选择花一周去实现一个功能,也能够给我吗一周时间重构,而后花一天去完成这个功能。可是第二种方案对于之后的开发有不少好处。

3.告诉客户,其实大家最终的目标是同样的。并且,大家担心的事情也是相似的。

一旦你和泥沼的主人达成一致,事实上最困难的事情就已经结束了。下面,让咱们的项目走上正确的方向吧

####不要再弄出一个新的沼泽地

你能够尝试修复它,不要重写它。

你可能说服了沼泽地的主人,你能够为他创造一个崭新的牧场。你会用更新的工具,更好的方式。可是,听个人,千万不要

从新的风险有不少:

1.这样作就像按下了一个危险的开关,新代码历来没在生产环境下跑过,谁都不知道会发生什么。

2.数据迁移,从旧的系统向新系统迁入和迁出数据很容易出现问题。

3.复刻旧的错误,你开始重写了,就有可能重复旧项目中的问题,旧项目的一些巧妙的特性也会被弄丢。不少问题都发生在系统的一些你自己刚开始就有疑问的地方。你会浪费不少时间,无论是你仍是你的客户。

4.你须要紧跟着业务,你在作新工程的时候,旧的工程也须要同时跟进业务需求。这样相同的东西须要在两边同时开展。

因此,听个人,不要从头开始,优化现有的

####让问题变得可见

这种事情很容易让人不爽,把问题都暴露出来。就像是让沼泽里的怪物们通通跑到了你的眼前向你的脸上吐痰,巨龙喷着火要烧掉你的头发,住在蘑菇旁的小侏儒踢着你的小腿。

无论你有没有注意到,这些害虫一直在侵蚀你的项目,你得想办法摆脱他们。因此必须得在任什么时候候都能看到到底问题出在哪

预见错误。每周花一点时间处理最常出现的一些问题。将问题图表化,可能能更有效的作到这一点,

监控环境变化。这多是找到瓶颈和预见危机的关键(见下文)。

这样,你就能知道是什么问题对你的项目伤害最大,你就能提前发现问题展开救治,而不是最后面对一个垂死的病人一筹莫展。

####处理最重要的问题

作到这一点。你就须要有一个对系统完整的目标。就像你清楚的知道你最终要构建的完美的牧场是什么样,在你的每一步工做都是朝着这个目标。

这样你就不会忘记你每一小步作了什么。在这一小步一小步中间,你就会发现本身到达了本身最终的目标。

结合上文所说的监控方式以及你的最终目标,肯定什么是你最早要处理的。你最大的问题应该不是立刻实现某个目标,并且开始管理重构路上你找出的问题

还有个建议,有些小问题就像是一写坡脚的小精灵,你可能看她们不爽,可是实际上她们是无害的。你最好把时间花到如何踢出真正对人有伤害的那些食人魔。

####这行代码是我写的

解决问题是最重要的,可是不意味着其中的实现细节不重要。事实上,他们一样重要。

这里有个沼泽生存原则,保持你的宿营地比你发现他的时候更干净。随着你持续的整理,注意不留下什么垃圾。你的环境就会愈来愈好直到你发现这篇泥沼变成了绿洲。

态度决定一切:

1.细心。代码是你写的,你要能向全部接触它的解释清楚它,不要草率马虎。

2.团队要同样细心。你辛苦的填上一个有一个坑,可是后来人还在不断挖坑的话,依然仍是那个样子。

3.纪律。团队任何一我的开始让事情变糟,都不要让他逃掉责任。

4.保持小步骤。在正确的方向上,进度比完美实现重要。

5.小小的胜利都能让人信心十足。你会发现一些地方优秀的修改会促使你想去修复它边上的问题。

####创建标准模块

一个对文明评价的重要指标是 在每平方米的土地上有多少图书馆。一样的,这对你的项目来讲也是一个相似的指标(固然在项目里咱们不叫他(Library)图书馆)。

举个例子,即便在最烂的沼泽地里,也会有几个不是特别糟糕的景点。不管什么时候,当你发现了一些好代码,他们完成了一些很不错的事情,就把他们挪到你的标准模块里,是的他们能够复用。

毫无疑问,你要修复的代码作的都是很差的。它们彻底忽略和和避开了能让程序员以为更轻松的能够陈祚最佳实践标准的原则。没有人会帮你搞定他们,你只有一条路可走:在你的新代码中实践下面的标准

让你的代码标准化和模块化。有些状况下你不得不使用旧的方式和不标准的方式处理旧的问题,可是这不意味着,你不能不在新的代码中实践这些正确的东西。

####用你的新模块重构 每当你的新模块写好,你就能够用它来重构旧的。你作这件事的时候不必向马拉松的冲刺阶段同样紧迫。每当你偶然发现你有一个好的新方式替代那部分老代码的时候。保持小步骤,最后你会发现一点一点你就找不到那些困惑你的老代码了。

一般,上述步骤是可行的。不过有时候你发现有些代码包含无数的依赖关系四处分布(好比会话访问,各类模块和服务纠缠在一块儿)。这时候,有个好方法是把它们的依赖方法和函数从他们内部暴露出来,外部就能够经过这些函数和方法访问他们。这种方式使得这些代码相对独立,之后更利于分离和移动它们。

同时,一旦代码独立了,它们就变得可测试了。

####经过测试创建信任

自由穿行的食人魔们能够比带着枷锁的食人魔更可怕。把系统中最为关键的部件(同时它们可能形成最严重的问题)加上锁链对于掌控一个系统是很是重要的。在每次构建的时候进行测试(最好是自动化的)尤其关键

若是有更多的对你的系统行为的自动化测试,你就能在改动项目的时候有更充足的信心。一点有东西出错,这些测试就能让你在发版前及时修改它们

####高级别测试

有一个有效的测试方式叫作:关键场景验收测试。对于一个电子商务系统,确定包括一个结帐的流程。没有订单你确定不赚钱,测试这个订单流程,你就能在客户没有发觉以前解决这个问题。有了这样的测试,你就能够避免本身不知不觉的引进重大问题

####低级别测试

这种低级别测试咱们推荐单元测试。使用上文说的小步骤逐一分解依赖的方式,你会使得你的代码有一套清晰的输入和输出结构。这种状况下就很适合用单元测试覆盖这些代码的功能。你能够定义一组输入,而且定义它预期的输出。这些测试能够确保这些代码的行为和你预期的一致

####不要测试全部的东西

不必测试系统的每一行代码。原则上让系统的每个方面可使咱们对全部事情充满信心,可是让全部东西可测试并为他们编写和维护测试用例会让成本变太高。根据个人经验,你最好把时间花在为重要的业务逻辑和有可能形成重大问题的代码上(即便他们看起来很简单)。

这样你就至关于把沼泽里最危险的怪物们锁起来了,整个沼泽变得更安全咯。

####隔离和更换

结合咱们上文提到的战略模式和技术,咱们总结惟一个原则:“隔离和替换”。

每当你遇到某些代码,他们的内部逻辑很难理解,并且打算用那种小步骤重构的方式整理出来。下面有些步骤建议:

1.隔离混乱的部分,把他们放到一些单独的方法里。

2.把依赖的部分拆出来做为他的参数

3.把逻辑里的反作用分离出来(好比向数据库保存数据),这里也是小步骤进行

4.隔离单独的逻辑到不一样的方法里

5.添加单元测试覆盖逻辑模块

6.重写的逻辑模块。就算他能经过测试,也要保证至少他的行为要相似老系统中的行为。

7.保持新老版本同时能在线上运行。保证旧版本也能运行

8.log记录下新老版本的输出。

9.对比日志,看看他们输出的不一样,若是有不一样就为该模块添加一个新的单元测试,而后开始修复它。

10.重复上述步骤直到他们一致为止。

11.最后新版本能彻底替换旧版本的相关逻辑

这种作法就像是不须要停车就能为他换了发动机,甚至是没有人能主要到他的内部发生了变化。

####说服本身

在这里,上述的态度和方法,至少对于我来讲,是一个拯救一个濒临崩溃的系统之路

最初我还在犹豫,为何要把个人时间花在这样一个长期的旧工程上。可是这期间我也得到了不少能帮助我变得更好的技能

1.识别糟糕的代码。你认识到什么是糟糕的代码由于你花了大量的是在在它上面。你在新项目中就不会使用它这种方式由于你知道它会在将来搞出多少问题。

2.回归本质。我认识到系统的每个方面都值得质疑和从新评估。项目里没什么是无懈可击的,你会发现许多更现代的框架能够帮你处理不少问题。

3.你和项目同时成长。随着你对项目的关注越多,你就会看到更多的挑战。你知道了哪些是这个系统的瓶颈,愈来愈多的人在依赖的工做成果,而你是整件事情的中心。

4.人们老是不断的生产新的东西。若是赶在在他们对项目形成伤害以前,理解他们的运做方式也是个不错的技能。

5.有趣的经历。回头看你这一路的历程,看看这个系统的样子和你几年前第一次遇到他的时候。是否是也蛮有成就感的呢。

####去完成这个巨大(至少是长期)的任务吧 你能够选择作一个胆小的农民,期待中谁能把你从这片沼泽地带到迪士尼乐园。或者你能够摆正你的姿态,扮演好救世主的角色。在任何一个有坚固地面的沼泽地里,你均可以找到你的位置。

####最后 几年以后,你漫步在这片牧场上。你看到公爵在地平线上竖起了啤酒广告代替了原来“这里有怪物”的标志牌。

######感受翻译的不太像人话。。。。

原文连接:http://blog.intracto.com/paying-technical-debt-how-to-rescue-legacy-code-through-refactoring

相关文章
相关标签/搜索