重构:改善既有代码的设计 笔记

重构的方式和流程

  • 两顶帽子:开发的时候,开发人员经常在两种状态间切换,或者带着重构的帽子重构代码,或者带着开发的帽子新增代码
  • 小步前进:由于重构不改变现有代码的逻辑,所以对于一个大功能,可以先重构一部分,测试,再接着重构一部分
  • 做好测试:重构都是修改现有代码,那么应当做到,以前能跑通的测试,重构后依旧可以跑通。这也是说,重构没有问题的一个表现是,通过所有预期的测试。

代码的坏味道(何时重构)

  • 重复代码、异曲同工的类
  • 过长函数:要写注释的地方,不妨分解一个函数,用函数名说明意图
  • 过大的类
  • 过长的参数列表:可以在函数内部通过调用其他函数得到的参数,可以不用通过入参得到
  • 发散式变化、霰弹式修改:每次变化都要修改多个函数的时候,不妨将修改的地方提取到一处或者一个类中
  • 依恋情节、狎暱关系:一个类对另一个类的数据和行为,比对自身更感兴趣,这时说明,类的功能划分有误
  • 数据泥团:几项数据,通常一起出现,一起被需要,那么,他们可能需要结成对象
  • 基本类型偏执:也许,使用小型对象,可以表示更多东西
  • switch语句:switch语句有时意味着,可以使用面向对象的继承和多态来避免
  • 面向未来编程、暂时性字段…:当前不用的字段和仅在一定情况下使用的字段,请谨慎编写
  • 中间类:当一个类基本把所有操作全转接给其他类处理时,这个类的作用就有待商榷,也许可以去掉
  • 被拒绝的遗赠:父类的全部方法,子类都应该继承,而不是选择一部分继承,如果是这样,可能父类需要把某些方法下沉

重构手法

重新组织函数

  1. 提炼函数/内联函数
  2. 引入解释性变量保存复杂表达式结果
  3. 将不同用途的临时变量区分开
  4. 使用函数对象取代函数:对于一个大型函数内,因为临时变量的缘故,函数无法拆解的情况,可以抽取函数对象,即保存变量,又有拆解的函数

对象之间搬移特性

  1. 搬移函数
  2. 搬移字段
  3. 提炼类/内联类
  4. 隐藏委托关系/移除中间类
  5. 引入外加函数/引入本地扩展(子类或者包装类)

重新组织数据

  1. 自封装字段:必要时再进行
  2. 以对象取代数据值
  3. 封装字段
  4. 封装集合(返回不可修改的集合)
  5. 以类取代类型码:当类型码不影响行为的时候,为了运行时检测安全,可以使用类取代类型码
  6. 以子类取代类型码:当类型码影响行为的时候,可以使用子类替代类型码,借助多态的优点,让与特定类型有关的代码下沉,这里对类型的取值函数,可以借用自封装字段
  7. 用状态模式/策略模式取代类型码:当类型码在对象存活期间会变化时
  8. 用类型码替代子类:当不同之处只在返回的类型码时

简化条件表达式

  1. 以卫语句取代嵌套条件表达式:就是将不合法的判断前置,提前return
  2. 以多态取代条件判断:首先,应当使用以子类/状态模式/策略模式替代类型码构建了继承体系,然后将条件判断的语句上移为抽象函数,由子类各自实现
  3. 引入null对象:在返回null的时候,考虑可否返回一个“空对象”,以避免反复的null校验

简化函数调用

  1. 移除参数:对于多态函数来说,复杂一些,需要考察是否每一个子类的实现都不需要这个参数
  2. 令函数携带参数/以明确函数名取代参数
  3. 以函数取代参数:函数入参可以通过调用其他参数即时获取,则无需入参
  4. 引入参数对象:为了抵抗前文提到的“数据泥团”
  5. 以工厂函数取代构造函数
  6. 以异常取代错误码
  7. 以测试取代异常

处理概括关系

  1. 字段上移/下移
  2. 函数上移/下移
  3. 构造函数上移
  4. 折叠继承体系:把子类融入父类
  5. 塑造模版函数:某些函数以相同顺序执行类似操作,将类似操作抽象相同签名,则某些函数的调用可以合并为一种,将其上移至超类
  6. 以继承取代委托/以委托取代继承:子类可能只需要父类的一部分功能,这时相对于继承,组合(委托)更为合适;反之,可以使用继承

个人感觉很有用的重构手法

  • 使用函数对象取代函数
  • 自封装字段
  • 以子类取代类型码
  • 引入null对象
  • 以卫语句取代嵌套条件表达式
  • 以异常取代错误码
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章