《重构》的读书笔记

ZhuYuanxiang 2019-01-09 00:00:00
Categories: Tags:

《重构》的读书笔记

学习基础

熟悉《设计模式》的基本概念,熟悉基本的 Java 语法,熟悉 Eclipse 和 JUnit 的使用,有相对较好的英语基础。

学习过程

学习目的

使自己编写的代码更容易被人读懂。

学习感悟

学习代码

Refactored-MartinFowler

总览

第 1 章 重构,第一个案例

1.1 起点 P_1

因为代码的结构无法满足添加新功能的需要,因此先进行重构,使代码方便添加新功能,然后再添加新功能。

1.2 重构的第一步 P_7

首先确认自己拥有一套可靠的测试机制,因为重构有可能引入问题,通过测试保证重构没有改变程序功能。

第 2 章 重构原则

2.1 何谓重构 P_53

重构 ( 名词 ) : 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高理解性和降低修改成本。
重构 ( 动词 ) : 使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
定义的扩展 :

重构的目标 : 只改变程序内部结构,不添加新的功能

不要一心二用 :

2.2 (P55)为何重构

2.3 (P57)何时重构

重构的三次法则 :

重构的时间点 :

复审团队 : 只要代码作者和一个审查者者。较大的项目可以通过 UML 图去展示代码的逻辑。

程序难以修改的原因 :

重构的目标 :

2.4 (P60)怎么对经理说

间接访问

很多时候重构都为程序引入间接访问 :

间接访问的价值 :

减少间接层的条件: 当间接层只在一处使用,那么需要将其消除。

2.5 (P62)重构的难题

数据库重构 :

接口重构

不重构的条件 :

2.6 (P66)重构与设计

重构与设计是彼此互补的 :

2.7 (P69)重构与性能

重构是有可能导致程序运行变慢的,但是不需要在设计和编码时就考虑性能问题。
例如 : 实时程序的编写 :

第 3 章 代码的坏味道

3.1 (P76)Duplicated Code ( 重复代码 )

3.2 (P76)Long Method ( 过长函数 )

原则 : 尽量利用函数名称来解释用途,而不是注释。
关键 : 代码主要用来描述“做什么”,而不是描述“怎么做”。例如 : getAge()表达获取年龄,而 today-birthday 就增加了理解的间接性,虽然看代码的人也能明白含义,但是就需要多想一下,并且 birthday 有可能表达的不是某个人的出生日期呢,而是某个买回来的产品的呢?那可能表达的就是使用时长了。
具体情况 :

3.3 (P78)Large Class ( 过大的类 )

有时候类并非在所有时刻都使用实例变量 : 使用 Extract Method 和 Extract Subclass ( 提炼子类 )

类中有太多代码 :

3.4 (P78)Long Parameter List ( 过长参数列 )

3.5 (P79)Divergent Change ( 发散式变化 )

不同的变化影响着相同的类发生改变,即变化的认知有分歧 ( Divergent ) 。
通过 Extract Class 把不同的功能封装到不同的类中,使每个类只因一种变化而需要修改

3.6 (P80)Shotgun Surgery ( 霰弹式修改 )

相同的变化会涉及到多个类发生修改,类似霰弹枪射击的效果。
可以通过 Extract Method,Move Method,Inline Class 把一种变化产生的多个修改移到同一个类中。

对比 :

3.7 (P80)Feature Envy ( 依恋情结 )

类中的某个函数对其他类的依赖度过高,则应该通过 Move Method ( 移动函数 ) 将它搬移到合适的类中。

3.8 (P81)Data Clumps ( 数据泥团 )

数据项总是成群结队出现,通过 Extract Class 将它们提炼到一个独立对象中,从而缩短参数列表,简化函数调用。

判断数据项是否相关的方法 :
如果这些数据项不在一起时就失去了明确的含义,那么就可以把它们提炼成一个新的对象。

3.9 (P81)Primitive Obsession ( 基本类型偏执 )

3.10 (P82)Switch Statements ( switch 惊悚现身 )

3.11 (P83)Parallel Inheritance Hierarchies ( 平行继承体系 )

每当为一个类增加子类必须也为另外一个类增加一个子类,那么就让一个继承体系的实例引用另一个继承体系的实例。

3.12 (P83)Lazy Class ( 冗赘类 )

没用的类,使用 Inline Class ( 内联类 ) 或者 Collapse Hierarchy ( 折叠继承体系 ) 来解决

3.13 (P83)Speculative Generality ( 夸夸其谈未来性 )

3.14 (P84)Temporary Field ( 令人迷惑的暂时字段 )

对象中某个字段仅为特定情况而设。使用 Extract Class ( 提炼类 ) 将这个字段提取出来

3.15 (P84)Message Chains ( 过度耦合的消息链 )

消息链 : 用户通过一个对象获取另一个对象,再通过获取的对象请求另一个对象,如此操作就是消息链。采取这种方式意味着客户代码将与查找过程中的导航结构紧密耦合,可以使用 Hide Delegate ( 隐藏“委托关系” ) 进行重构。但是谨慎处理!

3.16 (P85)Middle Man ( 中间人 )

过度委托形成中间人:Remove Middle Man ( 移除中间人 )

如果中间人还有其他行为,Replace Delegation with Inherited ( 以继承取代委托 )

3.17 (P85)Inappropriate Intimacy ( 狎昵关系 )

3.18 (P85)Alternative Classes with Different Interfaces ( 异曲同工的类 )

两个函数做了相同的事情却有不同的函数名称

3.19 (P86)Incomplete Library Class ( 不完美的库类 )

库函数功能不足,需要增加一些自定义的功能 :

3.20 (P86)Data Class ( 幼稚的数据类 )

幼稚的数据类 : 只有数据没有行为的类,其他类需要对该类的数据进行取值设值操作

3.21 (P87)Refused Bequest ( 被拒绝的遗赠 )

如果子类不愿意接受超类的所有定义,应该使用 Replace inherited with Delegation ( 以委托取代继承 ) 来处理子类

3.22 Comments ( 过多的注释 ) 87

使用 Extract Method ( 提炼方法 ) 来解决注释过多问题,注释更多应该说明的是“怎么做”,而不是“做什么”,例如 : 对一个排序函数说明其采用二分法排序,而不是说明它是个排序函数,因为这个说明在函数名称中已经具备。

第 4 章 构筑测试体系

4.1 自测试代码的价值 89

4.2 JUnit 测试框架 91

4.3 添加更多测试 97

第 12 章 大型重构 359

大型重构是程序开发必将遇到的,只是不知道在什么时间,用什么样的方式经历。例如 : 随着时间的推移,河道必定会被水草和垃圾所堵塞,你可以固定时间清淤,也可以放任自流直到崩溃。崩溃后依然会面临总结经验教训,再次重构系统。
大型重构很难给出具体的操作案例,因为每个大型案例相对于自身来说都是惟一的,是无法复制和重现的。可以复制与重现的都是这些大型重构中蕴含的具体的细节,因此这章主要讲的是思想和理念上的内容。
四个大型重构 :

第 13 章 重构,复用与现实 379

作为一个博士写的内容,仍然具有学术性较强的风格,可以当作历史资料了解一下重构的发展过程,也可以对重构的思想有更多理论上的认识。

安全重构 ( 391 )

安全重构的四条篱笆 :

重构工具

第 14 章 重构工具 401

相对于 10 多年前写的内容,现在许多 IDE 都已经提供了对大部分重构功能的支持。但是了解重构的基本理念,对于正确地使用重构工具会有很大的帮助。因为成功的重构不依赖于工具,而决定于人,当人做出了正确的决定,合理地使用重构工具辅助自己,才能保证重构的完成