为什么会拾起这本书来研读呢?一方面是因为近期在项目的更换中发现两个问题
- 读懂别人的代码不易,特别是在工程复杂的时候
- 自己写的代码能否让别人轻易读懂,包括后续的维护是否简易、扩展性是否足够。
- 写出让机器读懂的代码很正常,写出让别人轻易读懂的代码,才是优秀的。
手头上刚好有这么本书,希望能够在阅读和做总结的过程中,能不断严厉要求和规范自己,让自己的代码赏心悦目。得到近期荒废之后另一个进步。PS,估计目前只简记心得,后续如果有时间可以另外尝试分享现实经验。
《重构——改善既有代码的设计》(第二版)
前情,重构代码的一些抽象关键点
- 重构代码的步骤
- 确保有可靠的测试集,保证自己每一处修改可编译且不会引起新增问题
- 每一步都是粒度最小的改动,commit本地,一旦发现问题,可以最快的找到最后的改动点,避免在多步骤的改动后无法快速定位引起问题的改动点。
- 拆分,注意命名、变量、函数、多态。
- 重构不应该使原有功能面目全非,而是结构化调整。
- 两顶帽子 —— 添加新功能 & 重构,两者独立,但可以经常性交替。经常性地对代码进行重构,可以保证代码框架足够清晰,不会因为时间堆积而让代码越来越让人看不懂。
- 只要想重构,就需要有一套可以自测试的代码,来快速发现错误、避免错误。
- 重构有效的关键及协同效应。并且需要自我判断,是否需要重构。
- 自测试代码
- 持续集成
- 重构
- 重构影响性能,那么就关注在影响性能热点的小部分代码上(10%),让他发挥最大效用。
如何重构代码,什么代码需要重构
- 命名不规范
- 重复的代码
- 过长的函数
- 过长的参数列表 —— 参数的减少
- 全局变量引起的莫名bug & 可变数据 —— 封装变量
- Fancy Evny —— 策略模式和访问者模式
- 这里居然讲了24种,包括最后的注释,但慢慢地,看到中间部分,发现其实简单的重构方法,自己在平时项目中也有形成这种习惯了。
养成自测试的习惯
- 应该在开始编写模块的时候就写自测试代码,后续当你改动时,就可以通过这些代码保证改动的有效和准确
- 正常路径的测试,边界路径的条件也需要考虑(这个其实在自己的实践中经常被故意忽略,后续要养好习惯才行,如果你注意到边界行为,那么就需要去验证。)
一些重构的方法(作者的名录),从动机和做法出发
- 提炼函数
- 内联函数
- 提炼变量(这种在使用表达式较长的时候,可以提炼变量,使代码更容易阅读)
- 内联变量(当变量本身足够清楚表达含义时,就不需要提炼变量了)
- 改变函数声明
- 封装变量
- 引入参数对象(当多个函数使用了相同的参数时)
- 函数组成类(共同的函数作用范围,可以简单理解为当一些方法是有相同的共性的时候,比如提取一些工具类的方法)
- 函数组合成变换(需要派生信息的时候,enrich something, 当你的输入会得到一个变化的输出(同个对象,变化了)
- 拆分阶段
封装
- 封装记录,封装变量、封装到函数或者类中
- 以对象取代基本类型
- 添加中间人 & 移除中间人 (委托关系是否必要)
- 替换算法
搬移特性
- 搬移函数、搬移变量
- 搬移语句到函数中 <--> 搬移语句到调用者中
- 以函数调用取代内联代码
- 合并重复语句
- 拆分循环(让一个循环只做一件事情)
- 以管道取代循环(Replace Loop with Pipeline)【这个Colletion PipeLine的概念比较少使用到,后面关注】
- 移除死代码(如果是团队协同,那么就指操作自己部分的代码吧!想起了还没毕业的时候,第一次写一个业务需求,将别人的代码改动得乱糟糟,哈哈哈哈哈)
重新组织数据
- 拆分变量(移除对变量的赋值)
- 字段改名
- 以查询取代派生变量(Replace Derived Variable with Query)
- 将引用对象改为值对象 <--> 将值对象改为引用对象
简化条件逻辑
- 分解条件表达式
- 合并条件表达式
- 以卫语句取代嵌套条件表达式(Replace Nested Conditional with Guard Clauses)
- 以多态取代条件表达式
- 引入特例
- 引入断言(在目前的实际项目中,很少在应用层使用断言,一般在单元测试中使用)
重构API
- 将查询函数和修改函数分离(任何有返回值的函数都应该没有副作用)
- 函数参数化
- 移除标记参数(感觉是func test(A,B) -- > setA(B)
- 保持对象完整
- 以参数代替查询 -- 以查询代替参数
- 移除设置函数(如果不希望参数可以被改变,那就去掉setter吧)
- 以工厂函数取代构造函数
- 以命令取代函数(以函数对象取代函数) -- 以函数取代命令
处理继承关系
- 函数上移(下移)(子类中有相同的方法,可以移动到父类中)
- 字段上移(下移)
- 构造函数上移(下移)
- 以子类代替类型码(移除子类)
- 提炼超类 Extract Superclass
- 折叠继承体系(当子类和超类无太大区别)
- 以委托取代子类
- 以委托取代超类
其实好像是本书的目录结构,加上了一些自己的理解,也方便自己查看 (有些翻译很生涩,后续有空再仔细解说) 在记录总结的过程中,发现其实很多习惯已经在实际项目中使用且注意到了,欣慰。当然后面得更好地让自己养成习惯才好。
以上。