重构是在不改变软件客观行为的前提下改善其内部结构
“不改变软件行为”只是重构的最基本要求,要想真正让重构技术发挥威力,就必须做到“不需了解软件行为”
开始重构之前的两个建议,首先:把你的敬畏扔到太平洋里去,对于即将变得像空气与水一样普通的技术,你无需对它敬畏;其次,找到适合你的开发工具
懒惰是程序员的美德之一
设计模式为重构提供了目标。然而,“确定目标”只是问题的一部分而已,改造程序以达到目标,是另一个难题
坚持以重构行为来整理代码
所谓重构(refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。重构是一种经千锤百炼形成的有条不紊的程序整理方法,可以最大限度地减少整理过程中引入错误的几率。本质上说,重构就是在代码写好之后改进它的设计。
重构原则
一、何谓重构
重构(名词):对软件内部结构的一种调整,目的是在不改变软件客观察行为的前提下,提高其可理解星,降低其修改成本
重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构
首先,重构的目的是使软件更容易被理解和修改。其次,重构不会改变软件可观察的行为---重构之后软件功能一如以往。
两顶帽子
添加新功能,以及重构。添加新功能时,你不应该修改既有代码,只管添加新功能。重构时你就不能再添加功能,只管改进程序结构。
二、为何重构
重构改进软件设计
改进设计的一个重要方向就是消除重复代码
重构使软件更容易理解
让代码更好地表达自己的用途。这种编程模式的核心就是“准确说出我所要的”
重构帮助找到bug
重构提高编程速度
重构帮助你更快速地开发程序
三、何时重构
你之所以重构,是因为你像做别的什么事,而重构可以帮助你把那些事做好
三次法则
第一次做某件事时尽管去做;第二次做类似的事时会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构。
事不过三,三则重构
添加功能时重构
如果在前进过程中把代码结构理清,就可以从中理解更多东西。
重构是一个快速流畅的过程,一旦完成重构,新特性的添加就会更快速、更流畅。
修补错误时重构
复审代码时重构
让过程正常运转,你的复审团队必须保持精炼。最好是一个复审者搭配一个原作者,共同处理这些代码。复审者提出修改建议,然后两人共同判断这些修改是否能够通过重构轻松实现。果真如此,就一起着手修改。
如果是比较大的设计复审工作,运用UML示意图展现设计。
为什么重构有用
如果发现昨天的决定已经不适合今天的情况,放心改变这个决定就是,然后你就可以完成今天的工作了
让程序如此难以相与的四个原因:
---难以阅读的程序,难以修改
---逻辑重复的程序,难以修改
---添加新行为时需要修改已有代码的程序,难以修改
---带复杂条件逻辑的程序,难以修改
希望程序:①容易阅读②所有逻辑都只在唯一地点指定③新的改动不会危及现有行为④尽可能简单表达条件逻辑
四、怎么对项目经理说
如果经理嘴巴上说自己“质量驱动”,其实更多是“进度驱动”,这种情况下给一个较有争议的建议:不要告诉经理!
由经验可知,对于快速创造软件,重构可以带来巨大帮助。如果需要添加新功能,而原本的设计却又使我们无法方便地修改,而重构再添加新功能会更快些。如果要修补错误,就得先理解软件的工作方式,而我们发现重构是理解软件的最快方式。受进度驱动的经理要我们尽可能快速完事,至于怎么完成,就是我的事了。我认为最快的方式就是重构,所以我就重构。
五、重构的难题
坚决尝试一下重构,获得它所提供的利益,与此同时,也应该时时监控其过程,注意寻找重构可能引入的问题
数据库
重构经常出问题的一个领域就是数据库。绝大多数的商用程序都与它们背后的数据库结构紧密耦合在一起,这也是数据库结构如此难以修改的原因之一。另一个原因是数据迁移。就算你非常小心地将系统分层,将数据库结构和对象模型间的依赖降至最低,但数据结构的改变还是让你不得不迁移所有数据。
解决办法之一就是:在对象模型和数据库模型之间插入一个分隔层,这就可以隔离两个模型各自的变化。
修改接口
关于对象,另一件重要的事情是:它们运行你分开修改软件模块的实现和接口。你可以安全地修改对象内部实现而不影响他人,但对接口要特别谨慎---如果接口改变了,任何事情都有可能发生。
接口一旦发布,你就再也无法仅仅修改调用者而能够安全地修改接口了。你需要一个更复杂的流程。
发布接口很有用,但也有代价。所以除非真有必要,不要发布接口。
不要过早发布接口。请修改你的代码所有权政策,使重构更顺畅。
难以通过重构手法完成的设计改动
比如很难讲不考虑安全性需求时构造起来的系统重构为具备良好安全性系统。
何时不该重构
重写(而非重构)的一个清楚讯号就是:现有代码根本不能正常运作。
把未完成的重构工作形容为“债务”。把债务管理好是很重要的,你应该随时通过重构来偿还一部分债务。
六、重构与设计
重构肩负一项特殊的使命:它和设计彼此互补。
重构改变了预先设计的角色。如果没有重构,你就必须保证预先做出的设计正确无误,这个压力太大了。
如果选择重构,问题的重点就变了。你仍然做预先设计,但是不必一定找出正确的解决方案。
灵活的解决方案比简单的解决方案复杂许多。当然,如果最后发现所有这些灵活性都毫无必要,这才是最大的失败。
哪怕你完全了解系统,也请实际度量它的性能,不要臆测,臆测会让你学到一些东西,但十有八九你是错的。
七、重构与性能
“编写快速软件”的秘密就是:首先写出可调试的软件,然后调整它以求获得足够速度。
短期看来,重构的确可能事软件变慢,但它使优化阶段的软件性能调整更容易,最终还是会得到好的效果。