重构
2019-04-16 09:15:40 69 举报
AI智能生成
《重构,改善既有代码的设计》思维导图
作者其他创作
大纲/内容
重新组织数据
自封装字段
为字段建立取值/设值函数,并且只以这些函数来访问字段
以对象取代数据值
如果一个数据项需要与其他数据和行为一起使用才有意义,则将数据项变成对象
将值对象改为引用对象
如果一个类衍生出许多彼此相等的实例,则将他们替换为同一个对象,并通过引用调用
将引用对象改为值对象
如果一个引用对象很小并且不可变,为了易于管理,将其变为值对象
以对象取代数组
如果一个数组中的元素拥有各自不同的含义,则使用对象替换数组,用字段来表示数组中的每个元素
复制“被监视数据”
如果数据置于GUI中,那么应该将数据复制到对象中,并使用Observer模式同步数据
将单向关联改为双向关联
如果两个类都需要使用对方的特性,但其中只有一条单向连接,则添加一个反向指针,并修改函数能够同时更新两条连接
将双向关联改为单向关联
两个类之间有双向关联,但其中一个类已经不再需要另一个类的特性,则应该去除不必要的关联
以字面常亮取代魔法数
如果一个字面数值具有特别的含义,则应该创建一个常量,根据其意义为它命名,并将上述的字面数值替换为这个常量
封装字段
如果类中存在一个public字段,将它声名为private,并提供相应的访问函数
封装集合
如果一个函数返回一个集合,则应该让其返回该集合的一个只读副本,并在这个类中提供添加/移除集合元素的函数
以数据类取代结构体
使用数据类取代结构体,将数据体的所有字段封装为private字段,并提供相应的访问函数
以新类替换数值的枚举值
枚举值在大多数时候是以数值传递和检查,容易出现bug或者调试难以追踪,所以使用类来代替枚举类型,以使用运行时的类型检测
简化条件表达式
分解条件表达式
如果有一个复杂的条件语句,从if-then-else三个段落中分别提炼出独立函数
合并条件表达式
如果有一系列的条件判断都得到相同的结果,则将这些条件判断合并为一个条件表达式,并将这个条件表达式提炼成一个独立函数
合并重复的条件片段
如果在条件表达式的每个分支上有着相同的一段代码,则将这段重复代码搬移到条件表达式之外
移除控制标记变量
如果在一系列的布尔表达式中,存在控制标记变量,则使用break或者return取代控制标记变量
使用卫语句取代嵌套条件表达式
卫语句:单独检测的语句条件,条件为真时并立即返回
如果函数中条件逻辑中含有嵌套条件表达式,则使用多个卫语句替换嵌套逻辑
以多态取代条件表达式
如果一个条件表达式根据对象类型不同而选择不同的行为,则使用多态调用不同的重载函数来实现
引入Null对象
在需要检查对象不为Null时,才可以调用某些函数时,则可以引入相应的Null子类,并实现相应的函数,以向用户屏蔽Null对象的影响
引入断言
以断言明确表示代码需要对程序状态做出的某种假设
处理概括关系
字段上移
两个子类拥有相同的字段,则将字段移到他们的基类
函数上移
如果函数在各个子类中产生完全相同的结果,则将该函数移到他们的基类
构造函数本体上移
如果子类构造函数中有相同的部分,则将相同部分移到他们的基类构造函数中
函数下移
如果基类的某个函数只与部分子类有关,则将该函数移到相关的子类中
字段下移
如果基类的某个字段只被部分子类用到,则将该字段移到相关的子类中
提炼子类
如果类中的某些特性只被一部分实例用到,那么将这些特性移到新建的子类中
提炼超类
如果两个类有相似的特性,则为他们建立一个基类,并将相同的特性移到基类
提炼接口
将不同类中相同的子集提炼到独立接口类中
折叠继承体系
如果基类和子类之间并无太大差别,则将他们合为一体
塑造模板函数
若果子类之中有类似的函数,但又存有差异,那么将共同部分提炼到基类中,并添加重载函数保证其差异性
以引用取代继承
如果子类值使用了基类接口的一部分,或者根本不需要继承而来的数据,则将继承关系改为引用关系
以继承取代引用
如果一个类中许多函数只是简单的调用了另一个类的函数,那么让引用关系变为继承关系
重构
重新组织函数
提炼函数
将代码放进一个独立函数中,并让函数名称解释其用途
内联函数
如果一个函数的本体与名称一样清楚易懂,则应该将实现直接嵌入调用点,以减少不必要的间接层
内联临时变量
如果一个临时变量只被一个简单的表达式赋值一次,则应该将其替换为赋值表达式本身
以查询取代临时变量
如果一个临时变量用于保存某一表达式的运算结果,则应该将表达式提炼成函数,并将变量的引用替换为函数的调用
引入解释性变量
一个复杂的表达式,应该将其(或其中一部分)的结果放进一个临时变量,并以此变量名称来解释表达式的用途
分解临时变量
如果一个临时变量被赋值多次,既不是循环变量也不用于收集计算结果,则应该针对每一次赋值创造一个独立对应的临时变量,以避免混淆
移除对入参数的赋值
如果函数对一个入函数进行赋值,则用临时变量取代其位置。避免按值传递和按引用传递造成的混淆
以函数对象取代函数
如果一个函数中的局部变量使你无法方便地进行提炼,则将函数放进一个单独对象中,将局部变量变为成员变量,这样就可以顺利地进行提炼。
替换算法
使用更为简练快速的算法替换原函数
在对象之间搬移特性
搬移函数
如果类中的函数被其他类更为频繁的调用,则应该在其他类中建立有类似行为的新函数,并在原类旧函数中调用,或者将旧函数完全移除
搬移字段
如果类中的字段被其他类更为频繁的调用,则应该在其他类中建立类似的新字段,并修改原字段的所有用户,令他们改用新字段
提炼类
如果一个类具有多个职责,则应该针对每一个职责建立一个新类,并将相关字段和函数从旧类搬移到新类
内联类
如果一个类并没有完整的职责,则应该将这个类的所有特性搬移到另一个类中,然后移除原类
隐藏引用关系
如果客户类通过A类的函数获取B类对象的引用,然后调用B类的函数,则应在A类中建立客户类所需的所有函数,以隐藏A类对B类的引用关系
移除中间人
如果客户类过多地通过A类调用B类的函数,则应在A类中建立函数以获取B类对象的引用,直接调用B类的函数
引入外加函数
当你需要为服务类添加额外的函数,但是不能修改原类时,则在客户类中建立一个函数,并以第一参数形式传入一个服务类实例
引入本地扩展
当你需要为服务类添加额外的函数,但是不能修改原类时,则建立一个新类,使其包含这个额外的函数,让这个扩展类成为原类的子类或包装类
简化函数调用
函数改名
修改未能明确表达函数用途的函数名
添加对象参数
使用对象参数来代替过多的参数
移除参数
移除函数本体不需要的参数
将查询函数和修改函数分离
如果某个函数既返回对象状态值,又修改对象状态值,那么建立两个不同的函数,一个负责查询,另一个负责修改
令函数携带参数
如果若干函数做了类似的工作,那么建立单一函数,并以参数表达不同之处
以明确函数取代参数
一个函数完全取决于参数值不同而采取不同的行为,则针对每个可能的参数,建立一个独立函数
保持对象完整
如果函数的参数是某个对象中的一部分值,则将其改为传递整个对象
以函数取代参数
函数以另一个函数的结果为参数,如果可以那么去掉该参数,并在函数中调用其函数获取该值
引入参数对象
如果一些参数总是同时出现,则使用对象取代这些参数
移除设值函数
如果类中某个字段只在对象创建时赋值,则去掉该字段的设值函数
隐藏函数
如果一个函数从来没有在类外被调用,则将其设为私有
以工厂函数取代构造函数
如果创建对象时不仅仅是做简单的构建动作,则使用工厂函数替代直接使用构造函数
封装向下转型
如果函数调用者需要对函数的返回值进行向下转型,则将该动作封装到函数中
以异常取代错误码
如果函数使用错误码表示错误情况,则改用异常
以测试取代异常
以检查异常条件,取代抛出异常
大型重构
梳理并分解继承体系
如果一个继承体系同事承担两项责任,则建立两个继承体系,并通过引用关系调用
将过程化设计转化为对象设计
如果有传统过程化风格的代码,应将数据变成对象,大块的行为分为小块,并将行为移入相关的对象中
将领域逻辑与显示分离
如果某些GUI类中包含了领域逻辑,则应该将领域逻辑分离出来,并建立独立的领域类
领域逻辑:领域逻辑用来表达业务概念,保证业务规则,存放业务数据和业务状态等
提炼继承体系
如果某各类做了太多的工作,其中一部分工作是以大量的条件表达式完成的
建立继承体系,以一个子类表示一种特殊情况
0 条评论
回复 删除
下一页