何谓重构
重构一书中对重构的定义有两个:
定义1:
对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
定义2:
使用一系列的重构手法,再不改变软件可观察行为的前提下,调整其结构。
说明:
1. 重构的目的是使软件更容易被理解和修改。你可以在软件内部做很多修改,但必须对软件可观察的外部行为只造成很小的变化,或甚至不造成变化。与之形成鲜明对比的是性能优化。和重构一样,性能优化通常不会改变组件的行为(除了执行速度),只会改变其内部结构。但是两者出发点不同:性能优化往往使得代码很难理解,但为了得到所需的性能你不得不那么做。
2. 重构不会改变软件可观察的行为-重构之后软件功能一如以往。任何用户,不论最终用户或其他程序员,都不知道已经有东西发生了变化。
3. 使用重构技术开发软件时,你把自己的时间分配给两种截然不同的行为:添加新功能以及重构。添加新功能时,你不应该修改既有代码,只管添加新功能。通过测试,你可以衡量自己的工作进度,如果时间允许,然后做重构。重构时你就不能再添加功能,只管修改程序结构。软件开发过程中,你可能会经常变换这两个过程。首先你会尝试添加新功能,然后会意识到:如果把程序结构改一下,功能的添加会容易很多。于是你换一顶帽子,坐一会儿重构工作。程序结构调整好后,你又开始开发新功能。新功能正常工作后,你又发现自己的编码造成程序难以理解,于是又开始重构……整个过程或许只花了十分钟,但无论何时你都应该清楚自己处于哪个阶段。(重构一书中用两顶帽子来作比喻,很形象)
为什么重构
重构的目标是优化现有代码,也就是说我们要让现有的代码具有更好、更清晰的结构,提升他的可读性、可维护性、可扩展性。当我们的软件结构变得清晰时,我们后续的维护工作就会越来越容易,这样我们往后的工作量就会越来越少。(即重构可以提高软件的质量)
- 重构改进软件设计。因为我们不可能在软件的第一版时就保证我们的软件结构就是完全正确的,我们软件结构会随之系统的升级而演化。此时我们就需要重构代码以使系统适应变化。增加系统的扩展性、可维护性等等。否者我们的程序设计会逐渐腐化。改进设计的一个重要方向是消除重复代码。
- 重构使软件更容易理解。
- 重构帮助找到bug。重构使软件更容易理解。而这种理解,可以帮助我们找到潜在的bug。
重构提高编程速度。良好设计是维护软件开发速度的根本。重构可以帮助你更快的开发软件,因为它防止系统腐败变质,他可以提高设计质量。
难以阅读的程序,难以修改;
- 逻辑复杂的程序,难以修改;
- 添加新行为时需要修改已有代码的程序,难以修改;
- 带复杂条件逻辑的程序,难以修改;
因此,我们希望程序:1.容易阅读。2.所有逻辑都只在唯一地点指定。3.新的改动不会危及现有行为。4.尽可能简单表达条件逻辑。
重构是这样一个过程:他在一个目前可运行的程序上进行,在不改变程序行为的前提下使其具备上述美好性质,使我们能够继续保持高速开发,从而增加程序的价值。
什么时候重构
在我看来,重构不是一件需要安排一个特定的时间来做的事情,除非当前系统已经“腐化”到了非常严重的程度,否则重构应该随时随地进行。你不应该为了重构而重构,重构应该伴随在你的开发中,不断地开发、不断的重构,在开发的过程中持续重构以保持软件的优良结构。
虽然我们不建议单独找时间来进行重构,但仍然有一些时间节点是我们做重构的好时机。
三次法则
第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构。
- 添加功能时重构。此时,重构的一次个原因往往是为了帮助我理解需要修改的代码。这些代码可能是别人写的,也可能是我自己写的。当我发现我并不能很快速、直接的理解这段代码时,我就会考虑重构。之所以这么做是因为这段代码并不是那么容易理解,而我需要通过重构让它变得更简单、清晰。
- 修补错误时重构。
- 复审代码时重构。很多公司有review代码的机制,因为这种机制可以改善代码质量,也有助于在开发团队中传播知识,使缺乏经验的工程师能够从经验丰富的工程师身上学到知识。
代码重构的标志
见后文《代码的坏味道》
常见的重构手法概述
《重构:改善代码的既有设计》一书中的第6章讲重新组织函数,第7章讲的是在对象之间搬移特性,第8章重新组织数据,第九章是简化条件表达式,第十章是简化函数调用。第十一章是处理概括关系(继承)、第12章是大型重构。
以面对对象来把重构梳理一下:对象分为属性和行为。所以重构也从对象间(第7章讲的是在对象之间搬移特性、第十一章是处理概括关系)、对象的属性(第8章重新组织数据)、对象的行为(第6章讲重新组织函数、9简化条件表达式、10简化函数调用)等方面的考虑着手。
以下重构系列会分析一些常用的重构手法,快跟我来一起学习吧~~~
商业级开发:
在设计中引入灵活性的方法有:
降低耦合并提高内聚(易于提高替换能力);
建立抽象(创建有多态操作的接口和父类);
不要将代码写死(消除代码中的常数);
抛出异常(由操作的调用者处理异常);
使用并创建可复用的代码。
对象属性的重构
重构系列之对象属性的重构:《重构》重新组织数据
对象行为的重构
重构系列之对象行为的重构:《重构》重新组织函数
对象间的重构:
重构系列之对象间的重构:《重构》对象之间搬移特性
参考资料
http://www.cnblogs.com/angeldevil/p/3601730.html
31天重构:http://www.cnblogs.com/KnightsWarrior/archive/2010/06/30/1767981.html
http://toughcoder.net/blog/2014/10/25/tricks-to-remove-duplicates/
http://ifeve.com/fun-modules/
http://www.cnblogs.com/guanghuiqq/archive/2012/11/06/2756876.html