重构是什么
重构是在不改变外部行为的前提下改善代码内部结构,这是 Martin Fowler 在《重构》中给出的定义。它服务的是可理解性与可修改性:让下一次改动更快、更不容易出错。重构不产生新功能,也不等同于重写——重写会重建实现甚至改变对外行为,风险量级完全不同。
基本信息
| 定义 | 不改变外部行为,改善内部结构 |
|---|---|
| 前提 | 有可运行的测试,或可验证的行为基准 |
| 区别于 | 重写(重建实现)与性能优化(改变资源占用) |
| 最小单位 | 一次小步改动,改动后立即验证行为不变 |
| 常见误解 | 把重构当成专门排期的项目,而不是日常开发的一部分 |
什么时候值得重构
- 同一处代码为不同需求反复修改:结构已经跟不上变化方向。
- 加一个相似功能要复制粘贴一大段:抽象点缺失,重复成本在累积。
- 改一处要读五个文件才能确认影响:模块边界模糊,理解成本过高。
- 即将在附近继续开发:先把地基理顺,后续每一步都受益。
- 排障时发现逻辑绕但不敢动:先补行为测试,再用重构降低风险。
重构与相邻活动对比
| 活动 | 外部行为 | 内部结构 | 主要目标 |
|---|---|---|---|
| 重构 | 不变 | 改变 | 可维护性 |
| 重写 | 可能改变 | 重建 | 新需求与旧债 |
| 性能优化 | 通常不变 | 部分改变 | 速度与资源 |
| 修缺陷 | 改变(修复) | 尽量不动 | 正确性 |
重构的收益与代价
- 收益:改动速度回升,缺陷更容易定位,新人上手成本下降。
- 收益:边界清晰后测试更好写,回归防线反而更牢固。
- 代价:一定的时间投入,短期不产生可交付功能。
- 代价:没有测试保护时风险高,可能引入难以察觉的行为变化。
重构的产出是更清晰的代码,不直接产生新功能;两者混在同一提交里,评审者很难分辨哪一行改变了行为。
把重构嵌进日常开发(改动前先理顺附近结构)通常比集中排期更有效:收益立即可见,也不容易做成脱离需求的过度设计。