基本定义:重构(名词)是在不改变软件外在行为的前提下改善其内部结构。提高可理解性,降低修改成本。重构(动词)是使用一系列重构手法,在不改变软件外在行为的前提下,调整其结构。
第一章
-
如果你需要为程序添加一个新功能,而现有的代码结构使你无法很方便地达成目的,那就需要先重构现有的代码结构。
-
重构之前,首先检查自己是否有一套可靠的测试机制。这些测试必须有自我检验能力。
-
重构技术就是以微小的步伐修改程序。如果你放下错误,很容易便可以发现它。
第二章
重构的时机:
-
添加功能时
-
修改错误时
-
代码 Review 时
第三章
代码的坏味道:
-
重复代码
-
过长函数
-
过大的类
-
过长参数列
-
发散式变化:一个类受多个变化的影响
-
霰弹式修改:一种变化引起多个类的修改
-
依恋情节:引入了过多依赖
-
数据泥团:过于相同的对象
-
基本类型偏执:为做一两件事而创建的结构会太麻烦,不如采用基本类型
-
Switch 惊悚现身:尽可能用多态来替换
-
平行继承体系
-
冗余类
-
夸夸其谈未来型:某个抽象类作用不大
-
令人迷惑的暂时字段
-
过度耦合的信息链
-
中间人:过度运用委托
-
过度亲密关系:两个类过于耦合
-
异曲同工的类
-
不完美的库类
-
纯数据类:需要封装
-
被拒绝的遗赠:子类不实现支持超类的接口
-
过多的注释
第六章
重新组织函数
-
提炼函数:将过于长的代码放到几个合适的小函数里
-
内联函数:内联一些过于简短的函数到原调用方式里
-
内联临时变量:临时变量只是简单赋值一次,使用一次
-
以查询取代临时变量:将表达式提炼到一个独立函数
-
引入解释性变量:表达式难以理解时,引入临时变量来解释用途
-
分解临时变量:针对每次赋值,创造一个独立、对应的临时变量
-
移除对参数的赋值:对入参如果有修改,用临时变量承载
-
以函数对象取代函数:局部变量过多时,可以封装成一个对象来取代操作
-
替换算法:将函数本体替换成另外一个算法
第七章
在对象之间搬移特性
-
搬移函数:A类的某一个函数与B类过于耦合,则需要考虑将函数移动到B类
-
搬移字段:A类的某一个字段与B类过于耦合,则需要考虑将字段移动到B类
-
提炼类:某一个类做了应该由两个类做的事,则需要将类进行拆分成立两个类
-
内联类:一个类没做太多事情,合并到另一个类
-
隐藏“委托关系”:在服务类上建立客户所需的所有函数,用以隐藏委托关系
-
移除中间人:某个类做了过多的简单委托动作,需要客户直接调用受托类
-
引入外加函数:需要提供服务的类需要添加函数,但无法修改这个类,在客户类中建立一个函数,并将第一参数形式传入一个服务类实例
-
引入本地拓展:装饰器模式,来为之前的类新加功能函数
第八章
重新组织数据
-
自封装字段:通过为一个字段封装一个函数来代替访问方式
-
以对象取代数据值:将一个数据项封装成一个对象
-
将值对象改为引用对象:值传递改为引用传递
-
将引用对象改为值对象:引用对象很小且不可变不易管理,变成值对象
-
以对象取代数组:通过字段名字更能表达数据的用途
-
复制“被监视数据”:通过观察者模式来同步一些数据
-
将单向关联改为双向关联:两个类需要对方特性时,添加一个反向指针,可以同时更新
-
将双向关联改为单向关联:一个类不再需要另一个类的特性,移除不必要的关联
-
以字面常量取代魔法数:通过命名来标记用途
-
封装字段:对一个 public 字段改为 private, 并提供对应访问函数
-
封装集合:返回集合的副本,而不是原来的集合
-
以数据类取代记录:为传统编程环境的记录结构建立一个对象
-
以类取代类型码:为类型码新建一个类
-
以子类取代类型码:以子类取代一个不可变的类型码
-
以 State/Strategy 取代类型码:状态模式、策略模式来取代类型码
-
以字段取代子类:各个子类区别只在常量数据上,新增字段来销毁子类
第九章
简化条件表达式
-
分解条件表达式:从 if then else 中提炼出独立函数
-
合并条件表达式:一系列条件测试,返回同样的结果,合并成一个表达式并提炼成函数
-
合并重复的条件片段:每个分支都有相同的代码,移到表达式之外
-
移除控制标记:以 break 或 return 取代控制标记
-
以卫语句取代嵌套条件表达式:提早使用 return 来结束一段逻辑
-
以多态取代条件表达式:把分支放到子类里复写函数,将原始函数声明为抽象函数
-
引入 Null 对象:将 null 值替换成 null 对象
-
引入断言:以断言来表现程序状态的某种假设
第十章
简化函数调用
-
函数改名:函数名称自解释
-
添加参数:需要新的信息时,添加一个对象参数
-
移除参数:不再需要某个参数时,移除该参数
-
查询函数与修改函数分离:单一职责原则
-
函数携带参数:若干函数做了类似工作,添加一个参数合并这些函数
-
以明确函数取代参数:函数完全取决于参数值不同而采取不同行为,针对每一个可能取值,建立独立函数
-
保持参数完整:从某个对象取出若干值当入参,改为直接传递整个对象
-
以函数取代参数:某个函数的参数是另一个函数的结果,去除该参数,直接调用原函数
-
引入参数对象:某些参数总是同时出现,以一个对象取代这些参数
-
移除设值函数:某个字段在对象创建时被设值,然后不再改变,去除该字段的设值函数
-
隐藏函数:有一个函数从来没被其他类用到,函数修改为 private
-
工厂函数取代构造函数:可以在创建对象的时候,执行一些复杂的操作
-
封装向下转型:函数返回对象需要向下转型,应将向下转型在该函数中操作
-
以异常取代错误码:特定代码表示错误情况,改用异常传递
-
以测试取代异常:调用函数时先检查而不是直接抛出异常
第十一章
处理继承关系
-
字段上移:两个子类有相同的字段,上移至父类
-
函数上移:两个子类有相同的函数,上移至父类
-
构造函数本体上移:父类新建一个构造函数,子类去调用
-
函数下移:某个函数只与部分子类相关,将函数下放到子类
-
字段下移:某些字段只和部分子类有关,下放到子类
-
提炼子类:类的某些特性只被部分实例用到,新建一个子类将特性转移到子类中
-
提炼超类:两个类有相似特性,提炼出一个父类
-
提炼接口:两个类的接口有部分相同,提炼到一个独立接口
-
折叠继承体系:父类子类已无太大区别,合为一体
-
塑造模板函数:采用模板模式将一些函数封装成模板,子类去复写
-
以委托取代继承:子类只使用父类的一部分,组合方式代替继承
-
以继承取代委托:两个类有过多的接口以及委托函数,改为继承关系
第十二章
大型重构
-
梳理并分解继承体系:某个继承体系同时承担两项责任,建立两个继承体系,并通过委托关系让其中一个可以调用另一个
-
过程化设计转化为对象设计:数据记录变成对象,大块行为分为小块,行为移到类中
-
模型和显示分离:MVC 模式,将模型与显示分离
-
提炼继承体系:某一个类做了太多工作,一部分工作是大量表达式完成的,建立继承体系,以一个子类表示一种特殊情况