目录
第一章:重构,第一个实例
- 总结:通过一个简单的示例来理解重构的基本过程和效果
第二章:重构的原则
- 总结:重构的定义、原则、以及重构与性能的关系
- 何谓重构
- 重构(名词):对软件内部结构的一种调整目的是不改变软件可观测行为的前提下,提高其可理解性,降低修改成本
- 重构(动词):使用一系列的重构手法,在不改变软件可观测行为的前提下,调整其结构
- 重构原则:时刻保持软件可用:如果有人说他们的代码在重构过程中有一两天的时间不可用,基本上可以确定,他们在做的事情不是重构
- “两顶帽子”:添加新功能、调整代码结构
- 开发的时候自己可能经常变换帽子
- 为何重构
- 重构改进软件的设计:经常性的重构有助于代码维持自己该有的形态并消除重复代码
- 重构使软件更容易理解:代码不只给计算机用,还给其他的维护者用,经常的重构可以让人更能看懂代码的含义
- 重构帮助找到 bug:对代码进行重构,我就可以深入理解代码的所作所为,并立即把新的理解反映在代码当中。搞清楚程序结构的同时,我也验证了自己所做的一些假设,于是想不把bug揪出来都难。(以重构为驱动去理解代码?这里不是很理解)
- 重构提高编程速度:之前行业的陈规认为良好的设计必须在开始编程之前完成,因为开始编写代码后,设计就只会腐败,重构改变了这个图景。我们可以先做一个设计,然后随着需求的迭代不断改进它
- 何时重构
- 三次法则:事不过三,三则重构。第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构。
- 预备性重构:让添加新功能更容易
- 帮助理解的重构:使代码更易懂
- 捡垃圾式重构:每个小步骤都不会破坏代码,就像捡垃圾一样,积少成多
- 何时不应该重构
- 不需要修改的代码:不需要修改的代码,就不需要重构它。只有当需要理解其工作原理时,对其进行重构才有价值
- 何谓重构
第三章:代码坏味道
- 总结:如何识别代码中不好的地方
- 神秘命名:无法通过命名直观地知道变量或者方法的作用
- 重复代码:设法将结构相似的代码合而为一,程序会变得更好。一旦有重复代码存在,阅读这些重复的代码时你就必须加倍仔细,留意其间细微的差异。如果要修改重复代码,你必须找出所有的副本来修改。如果重复的代码段位于同一个超类的不同子类中,可以使用函数上移来避免在两个子类之间互相调用。
- 过长函数:函数的职责不够单一,导致直接违反开闭原则
- 作者介绍了一条原则:每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名
- 过长参数列表:如果可以向某个参数发起查询而获得另一个参数的值,那么就以查询取代参数,去掉这第二个参数
- 使用类可以有效地缩短参数列表。如果多个函数有同样的几个参数,引入一个类就尤为有意义
- 全局数据:全局数据代表全局任何一个地方都可以改变他而不受监控,一般需要通过封装变量的方式将这种全局的数据进行封装,通过方法进行改变
- 封装变量的好处:1. 利于监控与定位问题 2. 如果这个变量需要跟一些协同变量同时改变,函数可以做到收口
- 可变数据:尽量将查询和修改函数分开
- 发散式变化:某个模块经常因为不同的原因在不同的方向上发生变化,这就意味着这个模块已经违反了单一职责原则,需要进行分割
- 霰弹式修改:每次遇到某种变化,你必须在很多不同的类中进行小幅修改,这就说明你的模块拆分的过细
- 依恋情结:一个函数跟另外的模块的函数或者数据交流格外频繁,远胜于自己所处模块内部的交流。应该将这个函数跟另外的模块放到一起
- 数据泥团:如果你能在多个函数的参数中看到几个字段经常一起出现,这就是典型的数据泥团,应该将这些字段封装成类进行传递
- 好处是可以将很多参数列表缩短,简化函数调用
- 评判方法:删掉众多数据中的一项。如果这么做,其他数据不再有意义,这就是一个明确信号:你应该为它们产生一个新对象
- 基本类型偏执:比如区号、血型等业务逻辑,不要单纯的用 string 去表示这种类型,可以通过封装对象的方式取代基本数据类型进行业务逻辑表达
- 病症:
- 不愿意创建对自己问题域有用的基本类型,如钱、坐标、范围等
- 使用字符串做所有的事情
- 解决:用对象取代基本类型,将原本单独存在的数据值替换为对象
- 病症:
- 重复的 switch:用多态替代重复的 switch
循环语句:作者提倡使用管道(比如 js 的 map filter等操作符)取代循环(但是我不认为循环就是个坏味道)- 夸夸其谈的通用性:即过度设计
- 临时字段:特定情况临时加的
- 过大的类:类的职责过度,需要进行拆分
- 被拒绝的遗赠:如果拒绝父类的实现&接口,那继承父类就完全没有意义,不如通过以委托取代子类去代替继承关系
- 注释:注释意味着这里的函数可以再次拆分成更小的函数 & 函数的命名可以再次优化。这里并不是说完全不可以写注释
第四章:构筑测试体系
- 总结:要正确地进行重构,前提是得有一套稳固的测试集合
- 自测case的一些原则
- 让所有的测试都完全自动化,让它们自己检查测试结果
- 一套测试就是一个强大的 bug 侦测器,能够大大缩减查找 bug 所需的时间
- 总是确保测试case在不该通过时真的会失败
- 频繁地运行测试,对于你正在处理的代码,与其对应的测试至少每隔几分钟就要运行一次,每天至少运行一遍所有的测试
- 测试 case 不要求过度完美,编写未臻完善的测试并经常运行,好过对完美测试的无尽等待。
- 将UI与业务逻辑隔离,这样才能写测试用例直接测逻辑部分
- 考虑可能出错的边界,把测试火力集中到那里
- 不断探索程序的错误边界反过来可以提高我们正向编程的能力
- 不要幻想把所有场景都覆盖测试,只覆盖那些关键、容易出错的地方就够了,不然会因为工作量太大而气馁
- 每当你收到一个 bug 时,请先写一个单元测试来暴露这个问题
第五章:介绍重构名录
第六章:第一组重构
第七章:封装
第八章:搬移特性
第九章:重新组织数据
重构改善既有代码的设计-学习(三):重新组织数据-CSDN博客
第十章:简化条件逻辑
重构改善既有代码的设计-学习(四):简化条件逻辑-CSDN博客
第十一章:重构API
重构改善既有代码的设计-学习(五):重构API-CSDN博客