重构-改善既有代码的设计(十二):大型重构

1、梳理并分解继承体系(Tease Apart Inheritance)

(1)症状:某个继承体系同时承担两项责任

(2)解决:建立两个继承体系,并通过委托关系让其中一个可以调用另一个

(3)混乱的继承体系是一个严重的问题,会导致重复代码

(4)将代码较多的职责留在原地,这样一来需要搬移的代码数量就会比较少

(5)如果继承体系中的某一特定层级上的所有类,其子类名称都以相同的形容词开始,那么这个体系很可能承担着两项不同的责任

  • 首先识别出继承体系所承担的不同责任,然后建立一个二维表格,并以坐标轴标示出不同的任务
  • 判断哪一项责任更重要些,并准备将它留在当前的继承体系中,准备将另一项责任移到另一个继承体系中
  • 使用Extract Class从当前的超类提炼出一个新类,用以表示重要性稍低的责任,并在原超类中添加一个实例变量,用以保存新类的实例
  • 对应于原继承体系中的每个子类,创建上述新类的一个子类,在原继承体系的子类中,将前一步骤所添加的实例变量初始化为新建子类的实例
  • 针对原继承体系中的每个子类,使用Move Method将其中的行为搬移到与之对应的新建子类中
  • 当原继承体系中的某个子类不再有任何代码时,就将它去除
  • 重复以上步骤,直到原继承体系中的所有子类都被处理过为止,观察新继承体系,看看是否有可能对它实施其他重构手法,例如Pull Up Method或Pull Up Field

 

2、将过程化设计转化为对象设计(Convert Procedural Design to Object)

(1)症状:有一些传统过程化风格的代码

(2)解决:将数据记录变成对象,将大块的行为分成小块,并将行为移入相关对象之中

  • 针对每一个记录类型,将其转变为只含有访问函数的哑数据对象
  • 针对每一处过程化风格,将该处的代码提炼到一个独立类中
  • 针对每一段长长的程序,实施Extract Method及其他相关重构将它分解,再以Move Method将分解后的函数分别移到它所相关的哑数据类中
  • 重复上述步骤,直到原始类中的所有函数都被移除,如果原始类是一个完全过程化的类,将它拿掉

 

3、将领域和表述/显示分离(Separate Domain from Presentation)

(1)症状:某些GUI类之中包含了领域逻辑

(2)解决:将领域逻辑分离出来,为它们建立独立的领域类

(3)MVC模式的核心价值在于:它将用户界面代码(视图)和领域逻辑(模型)分离了

  • 为每个窗口建立一个领域类
  • 如果窗口内有一张表格,新建一个类来表示其中的行,再以窗口所对应之领域类中的一个集合来容纳所有的行领域对象
  • 检查窗口中的数据,如果数据只被用于UI,就把它留着;如果数据被领域逻辑使用,而且不显示于窗口上,就用Move Field将它搬移到领域类中,如果数据同时被UI和领域逻辑使用,就对它实施Duplicate Observerd Data,使它同时存在于两处,并保持两处之间的同步
  • 检查展现类中的逻辑,实施Extract Method将展现逻辑从领域逻辑中分开,一旦隔离了领域逻辑,再运用Move Method将它移到领域类
  • 以上步骤完成后,就拥有了两组彼此分离的类:展现类用以处理GUI,领域类包含所有业务逻辑

 

4、提炼继承体系(Extract Hierarchy)

(1)症状:有某个类做了太多工作,其中一部分是以大量条件表达式完成的

(2)解决:建立继承体系,以一个子类表示一种特殊情况

(3)只有当条件逻辑在对象的整个生命周期保持不变,本重构所导入的策略才适用,否则你可能必须在分离各种状况之前先试用Extract Class

  • 鉴别出一种变化情况
  • 针对这种变化情况,新建一个子类,并对原始类实施Replace Constructor with Factory Class将它提炼为一个独立的类
  • 将含有条件逻辑的函数,一次一个,逐一复制到子类,然后在明确情况下(对子类明确,对超类不明确),简化这些函数
  • 重复上述过程,将所有变化情况都分离出来,直到可以将超类声明为抽象类为止
  • 删除超类中那些被所有子类覆写的函数本体,并将它们声明为抽象函数

如果非常清楚原始类会有哪些变化情况,可以使用另一种做法

  • 针对原始类的每一种变化情况,建立一个子类
  • 使用Replace Constructor with Factory Method将原始类的构造函数转变成工厂函数,并令它针对每一种变化情况返回适当的子类实例
  • 针对带有条件逻辑的函数,实施Replace Conditional with Polymorphism,如果并非整个函数的行为有所变化,而只是函数一部分有所变化,先运用Extract Method将变化部分和不变部分隔开来

 

尾注

  • 上述的总结与思考是基于对《重构—改善既有代码的设计》这本书的精读与演绎
  • 更多及时干货,请关注微信公众号:JAVA万维猿圈

重构-改善既有代码的设计(十二):大型重构_第1张图片

你可能感兴趣的:(读书笔记)