Refactoring Skills

Refactoring Skills

一月 20, 2019 阅读 101 字数 4634 评论 0 喜欢 1

重构的具体手法

6.重新组织函数

6.1Extract Method提炼函数

多使用小函数,即使函数名比函数体长也无所谓,关键是提炼后能够通过函数名知道这个函数干什么

6.2Inline Method内联函数

在函数调用的地点插入函数本体,然后移除该函数.注意该函数不能具有多态性

6.3Inline Temp内联临时变量

如果临时变量影响了重构,就把该变量去掉,所有引用了该变量的地方换为对该变量赋值的语句,并注意观察后续对这个变量的操作.这两点其实就是链式表达式的使用.

6.4Replace Temp with Query以查询取代临时变量

程序以一个Temp保存某一表达式的值,将这个表达式提炼到一个函数.(这不是和Inline Method矛盾了~orz)

6.5Introduce Explaining Variable引入解释性变量

与上一条相反

6.6Split Temporary Variable分解临时变量

某个变量被赋值多次,该变量既不是循环变量,也不似用于统计数据,应该针对每次赋值创建一个独立的临时变量

6.7Remove Assignments to Parameter移除对参数赋值

代码对一个参数进行赋值,应该以一个临时变量取代该参数的位置,这个是针对Java来说的,至于C++的话,少用传入参数

6.8Replace Method with Method Object以函数对象取代函数

某个大型函数要进行重构,但是局部变量太多,可以把这个函数放进一个单独的对象,把局部变量变为了成员变量,然后可以对这个大型函数分解,这里指的的函数对象,并非是C++重载了()的functor

6.9Substitute Algorithm替换算法

把复杂的算法替换为简单的.

7.在对象之间搬移特性

7.1Move Method搬移函数

如果一个类与另一个类有太多耦合关系,尝试搬运函数

7.2Move Field搬移字段

7.3Extract Class提炼类

一个类干一个类的事,以符合单一职责原则

7.4Inline Class将类内联化

如果一个类没有做太多的事,将该类所有特性搬移到另一个类中.如果以一个接口代替该类更合适的话,内联化之前先Extract Interface

7.5Hide Delegate隐藏委托关系

像John.getDepartment().getManager()这样的调用关系会暴露Department的结构,可以设计为为调用类增加接口John.getManager()

7.6Remove Middle Man移除中间人

某个类做了过多的简单委托关系,让客户直接调用委托类

7.7Introduce Foreign Method引入外加函数

你需要为提供服务的类增加一个函数,但你无法修改这个类

7.8Introduce Local Extension引入本地扩展

你需要为服务类提供一些额外函数,但你无法修改这个类.

建立一个新类,使他包含这些额外函数,让这个扩展品成为源类的子类或者包装类

8重新组织数据

8.1Self Encapsulate Field自封装字段

为字段设置取值设值函数

8.2Replace Data Value with Object以对象取代数据值

8.3Change Value to Reference将值对象改为引用对象

从一个类中衍生出许多彼此相等的实例,需要将他们替换为同一对象,单例模式

8.4Change Reference to Value将引用对象更改为值对象

引用对象太小且不好管理

8.5Replace Array with Object以对象取代数组

数组中每个元素代表的不是同种类型的数据

8.6Duplicate Observed Data复制被监视的数据

观察者模式

8.7Change Unidirectional Association to Bidirectional将单向关联改为双向关联

两个类都需要使用对方特性,但其间只有一条单向连接,运用反向指针实现双向连接

8.8Change Bidirectional Association to Unidirectional将双向关联改为单向关联

8.9Replace Magic Number with Symbolic Constant以字面常量取代魔法数字

也就是使用宏来代替数字

8.10Encapsulate Field封装字段

8.11Encapsulate Collection封装集合

8.12Replace Record with Data Class以数据类取代记录

8.13Replace Type Code with Class以类取代类型码

如果类型码不会影响类的行为,使用新的类取代类型码

8.14Replace Type Code with Subclass以子类取代类型码

如果类型码会影响类的行为,使用子类的多态取代类型码,这样的继承体系应该以类型码的宿主为基类,创建各种类型码对应的子类,如果有不适合这种做法的,比如宿主有自己子类,或者类型码会改变,采用Strategy模式

具体手法:1)使用8.1的手法把类型封装get方法;2)建立子类,覆写类型码的取值函数

8.15Replace Type Code with State/Strategy以状态机/策略模式取代类型码

在上一个手法不能用多态处理的情况下,采用这种手法.

具体手法:1)使用8.1的手法把类型封装get方法;2)新建一个类,根据类型码用途命名,这就是一个状态对象;3)为这个类添加子类,每个子类对应一种类型码;4)在基类中建立一个抽象查询函数,用以返回类型码;5)在源类中建立一个字段,用以保存新建的状态对象;6)调整源类中的类型码设值函数,将一个状态对象子类赋值给保存状态对象的字段

8.16Replace Subclass with Field一字段取代子类

子类的差别仅在返回常量数据的函数上.

9简化条件表达式

9.1Decompose Conditional分解条件表达式

对于过于复杂的大段if-else,提取各自的独立函数

9.2Consolidate ConditionalExpression合并条件表达式

如果一系列的条件测试,都得到相同结果,使用逻辑或.使用逻辑与处理多个判断,多使用三目运算符.

9.3Consolidate Duplicate Conditional Fragments合并重复的条件片段

在每个条件判断的分支有相同的代码片段.

9.4Remove Control Flag移除控制标记

使用break,continue或者return取代flag.

9.5Replace Nested Conditional with Guard Clauses 以防卫语句取代嵌套条件表达式

如果某个条件极其罕见,首先单独检查该条件.防卫语句要么返回,要么抛异常.或者采用条件反转:判断原条件的相反条件.

9.6Replace Conditional with Polymorphism以多态取代条件表达式

将条件表达式的每个分支放进一个子类的覆写函数中,然后将原始函数声明为抽象函数

9.7Introduce Null Object引入Null对象

当你需要再三检查对象是否为空时,引入Null对象

手法:为源类建立一个子类,其行为就像源类的Null版,在源类和子类都加入isNull()的函数

9.8Introduce Assertion引入断言

10简化函数调用

10.1Rename Method函数改名

10.2Add Parameter添加参数

10.3Remove Parameter移除函数

10.4Separate Query from Modifier将查询函数和修改函数分离

10.5Parameterize Method令函数携带参数

若干个函数做了类似的工作,但在函数本体中却包含了不同的值,新建一个带有参数的函数,使它可以替换先前的重复性函数.

10.6Replace Parameter with Explicit Method以明确的函数取代参数

某个函数的行为完全取决于参数.针对每个参数的可能值,建立独立函数.

10.7Preserve Whole Object保持对象完整

有时候以某个对象的若干数据作为参数,就直接传递对象

10.8Replace Parameter with Method以函数取代参数

参数的接收端也能调用函数,也就是最终使用参数的函数有办法获得参数值,不需要靠参数传递.如果有必要,将参数的计算过程提炼到一个独立的函数

10.9Introduce Parameter Object引入参数对象

某些参数总是很自然同时出现,新建一个类,往往能在提炼出一些操作这些参数的函数.

10.10Remove Setting Method移除设值函数

某个值在对象创建后不再改变,在构造函数设值参数值就行了.

10.11Hide Method隐藏函数

某个函数没有被其他类使用,应该改为private.

10.12Replace Constructor with Factory Method以工厂函数取代构造函数

希望在创建对象的时候不仅仅做简单的构建动作.

手法:1)新建一个工厂函数,让它调用现有的构造函数;2)将构造函数声明为private

10.13Encapsulate Downcast封装向下转型

10.14Replace Error Code with Exception以异常取代错误代码

10.15Replace Exception with Test以测试取代异常

11处理概括关系

11.1Pull Up Field字段上移

两个子类拥有同样的字段

11.2Pull Up Method函数上移

如果两个函数相似但不同,可以使用Form Template Method构造出相同的函数,然后在提升它,如果被提升的函数引用了子类的特性,那么看是否可以将该特性也提升.

11.3Pull Up Constructor Body构造函数本体上移

11.4Push Down Method函数下移

11.5Push Down Field字段下移

11.6Extract Subclass提炼子类

类中的某些特性只被某些实例用到

11.7Extract Superclass提炼超类

两个类有相似的特性

11.8Extract Interface提炼接口

11.9Collapse Hierarchy折叠继承关系

超类和子类无太大区别

11.10Form Template Method塑造模板函数

11.11Replace Inheritance with Delegation以委托取代继承

某个子类只使用超类接口的一部分,不需要继承而来的数据

做法:在子类中新建一个超类对象的字段,修改子类的函数,使其不再使用超类,改用该字段,然后移除继承关系

11.12Replace Delegation with Inheritance以继承取代委托

在两个类之间使用委托,并经常为整个接口编写许多极简单的委托函数

12大型重构

12.1Tease Apart Inheritance梳理并分解继承体系

某个继承体系同时承担两项责任

做法:建立两个继承体系,并通过委托挂你让其中一个可以调用另一个

12.2Convert Procedural Design to Object将过程化设计转化为对象设计

12.3Separate Domain from Presentation将领域和表述分离

某些GUI类中包含了领域逻辑,将领域逻辑分离为领域类

12.4Extract Hierarchy提炼继承体系

有某个类做了太多工作,其中一部分工作是以大量条件表达式完成的,建立集成体系,以一个子类表示一种情况

发表评论

电子邮件地址不会被公开。