重构: 改善既有代码的设计
- 重构的前提
- 重构的前提是有一套可靠的测试集
- 好代码的检验标准是人们可以轻而易举的读懂并修改它
- 重构过程中应时刻保持应用可以通过所有测试集
- 重构时应清楚自己是在重构代码还是在添加新功能
- 为何重构
- 何时重构
- 添加新功能时
- 为了帮助理解时
- 发现问题时,记录下来有空再处理
- 为了系统的健壮性,有计划的去重构
- 何时不重构
- 在需要理解内部详细情况下不重构
- 如果重写比重构简单,那么重写
- 坏代码
- 神秘命名:不明白的意思的名称 -> 名称应与业务逻辑相关
- 重复代码: 多个地方的逻辑是一样的 -> 整合重复代码
- 过长的函数: 会让人不知道到底做什么 -> 提炼函数,命名规整
- 过长的参数列表: 会让人疑惑 -> 使用结构
- 全局数据: 容易被其他地方修改而不知
- switch : 应使用多态来实现
- 注释:应用命名代替注释,对于复杂的或者特别的可以注释说明
- 编写测试用例的好处
- 可以更清楚知道自己是否有bug
- 更全局的考虑场景和代码吻合度
- 如何编写测试
- 针对某一特定功能 (容易错的地方)
- 写特别有的针对性的用例
- 用全局变量时注意多个用例共用时可能出现的问题
- 有bug时,先写测试用例来暴露它,以便解决它
- 重构建议
- 尽量小步的重构,确保每个部位都是正确的
- 注意多个方法使用同一个引用对象时发生的事情,可能超出你的意料
- 在构建足够清晰的代码时,可以考虑使用内联或者提炼,让表达更清晰。
- 当一个逻辑十分复杂时,考虑使用局部变量来让他简短而明了。
- 封装数据时,考虑是否应该共享源数据。(不需要可以返回副本)
- 将每个步骤区分开,提取各个步骤所需的公共数据,让逻辑更清晰
- 重构方式
- 封装:封装变量,定义类职责,思考应该暴露的概念,以及期望的效果
- 搬移特性:将变量或方法定义在符合设计的地方,以便理解和合理建模
- 重新组织数据:定义变量或者使用时候,要考虑到使用时如果被修改,可能造成的影响,比如在方法中传入对象,如果方法内修改了对象的内部变量值,可能影响其他使用者。
- 简化条件逻辑:变量的逻辑判断给人的感受不如用文字表明的一个包装函数直观,适当使用断言帮助理解行为,使用多态来分解逻辑判断的难理解或共同点
- 重构API:一个函数尽量制作一件事情,函数参数传变量还是对象基于函数作用考虑
- 处理继承:将重复的代码尽可能移动到父类中。 不要过度设计导致滥用继承。继承应该作为具有相同行为的对象的一种抽象。 适当使用委托来减少过度的继承
一切都是为了便于理解。
本书6-12章讲述重构的手法,不一定都会用上,只是说明遇到某些情况,你可以使用它。
其他书籍 : 《修改代码的艺术》 《设计模式》