在第一章作者用一个例子让我们感受重构,在第二章中作者着重讲了一下重构的关键原则,
和重构时应该考虑的问题。
2.1 何谓重构
重构名词定义:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高
其可理解性,降低其修改成本。
重构动词定义:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
扩展的两个点:1. 重构使软件更容易被理解和修改,而性能优化通常也不会改变组件的行为
只会改变其内部结构。但是性能优化之后代码一般更难理解。
2. 重构不会改变软件的可观察行为——重构之后软件的行为一如既往。
两顶帽子:软件开发的时候可以把时间分配给两种截然不同的行为:添加功能
重构
重构时不要添加新的功能,只管改进程序结构。
添加新功能时,不应该修改既有代码,只管添加新功能,通过测试来衡量进度。
在开发的时候两种行为可能经常发生变化,但是你得清楚自己是处于那种状态。
2.2 为何重构
重构改进软件设计:程序会腐化,不良代码的特征就是到处是重复代码,代码越多修改越复杂,在一处修改了还要在另外一个地方修改。
重构使软件更容易理解:在我们编写程序的时候注重更多的是让计算机去执行我 们的指令,但是除此之外我们写的代码还是要给别人看的,而且大概率是自己后在后面该这段代码。花一点时间进行重构,可以让代码更好地表达自己的用途。
重构帮助找到bug:对代码进行重构,可以深入理解代码的作为,并恰到好处地把理解反馈回去。
重构提高编程速度:改善设计、提升可读性、减少错误,良好的设计是快速开发的根本。
2.3 何时重构
三次法则:第一次,第二次有个大概印象,但是如果遇到了第三次就得重视起来了,就好像记阅读中的单词一样。
添加功能时重构:添加功能时重构可以帮助理解理解代码,重构是对设计一种补充
修补错误时重构:重构代码使代码更具有可读性,加深对代码的理解可以帮助找到bug
复审代码时重构:阅读代码-->理解-->提出建议,想到点子-->考虑重构来实现-->更高层次的认识
为什么重构有用:
程序的价值:今天做什么,明天可以做什么,系统当下的行为和系统明天的综合考虑
难以阅读的程序,难以修改 --> 容易阅读
逻辑重复的程序,难以修改 --> 所有逻辑都在唯一地点指定
添加新行为需要修改已有的代码,难以修改 --> 新的改动不会危及现有行为
带复杂条件逻辑的程序,难以修改 --> 尽可能用简单表达条件逻辑
2.4 怎么对经理说
经理:1. 质量驱动:会理解程序员,这时可以在复审的时候重构,减少错误,提高开发速度
2. 进度驱动:"不要告诉经理",重构可以快速构造软件。
1. 添加新功能但又不方便修改原本的设计,重构可以使新功能的添加更快
2. 如果是修补错误,重构可以加快对软件的理解
间接层和重构
重构引入了更多的间接层。
允许逻辑共享:一个子函数可以在不同的地方被调用
分开解释意图和实现:可以选择每个类和函数的名字来解释自己的意图
隔离变化:在两个地方使用同一对象,其中第一个地方的修改可能会影响另一个,这时可以用子类来隔离变化
封装条件逻辑:多态消息可以灵活表达条件逻辑,将条件逻辑转化为消息形式,减少代码重复
找出值得的间接层,避免全盘错误,程序自始至终都能保持一致性
找出不值得的间接层,原来希望在多个地方用到的,但是最终只在一个地方用到了,可以把它拿掉
2.5 重构的难题
数据库:
现状:程序一般都和数据库紧密耦合在一起,改了数据库结构通常都要修改对象模型。有可能还要迁移数据
解决:非对象数据库中加入一个中间层,可以隔离出两个模型各自的变化。
修改接口:
现状:对象和接口和实现可以分开修改,可以安全地修改内部的实现不影响他人;但是对于接口的修改就要特别谨慎,尤其是公开发布的接口。
解决:保留新旧接口,实现时让旧接口调用新接口的实现,典型的例子就是Java的容器类型。
不要发布或过早发布接口,只有在必要的时候才发布接口
难以通过重构手法完成的设计改动
现状:重构并不能够排除所有的设计错误,比如将不考虑安全性的系统重构为具备良好的安全性
解决:考虑设计方案的时候先考虑到重构成另一种设计的时候难度有多大
何时不该重构
现状:代码太混乱以至于重新编写所有的代码比重构还简单,重写的信号是:现有的代码根本不能正常运作(通过测试可以发现);
如果快到deadline的话,应该避免重构;
解决:直接重写代码,或者将"大块头软件"重构为封装良好的小型组件;
如果最后没有时间重构,说明你没有及早重构,因为重构确实能提高生产力。
2.6 重构与设计
浑浑噩噩写代码 <---> 事先做好设计科比节省返工的成本:软件的可塑性强,而且完全是思想的产品
重构可以取代设计:不做任何设计,只按照最初的想法编码,让代码有效运作,然后再将它重构成型,极限编程
如果没有重构,就必须保证预先做出的设计正确无误,压力太大。
重构可以带来更简单的设计,同时又不损失灵活性,降低了设计的难度。
2.7 重构与性能
重构是否影响性能?
不赞成为了提高设计的纯洁性而忽视性能,重构可能会使软件工作得更慢,但是性能优化做起来更为容易。
性能优化阶段,用一个度量工具来监控程序运行,告诉你哪里会大量消耗时间和空间。找出热点代码。
发现热点,去除热点。
构造良好的程序:让你有时间进行性能调整,因为可以更快地添加新功能
性能分析有更细的粒度,度量工具可以把你带入较小的程序段落中,性能调整更容易
总而言之,重构确实会降低程序性能,但会让你更容易调整软件的性能。
2.8 重构起源何处
refactoring(重构)
优秀的程序员至少会花一些时间来清理自己的代码,简洁的代码比杂乱无章的代码更容易修改。
实例:优化一个薪资系统