不敢重构的代码库:从「先加测试」开始的四步法
老代码没人敢动,不是因为它复杂,是因为「改错了没人知道」。
重构的第一步不是改结构,而是建立反馈:让改动立刻能被验证。
先说结论
先写特征测试锁行为,再小步替换,最后删旧代码。 每次提交都要能回滚。
- 特征测试记录「当前行为」,不判断对错
- 重构与改功能分两个提交
- 用绞杀者模式:新逻辑并行跑,比对结果
- 每次合并保持主干可发布
先把问题说清楚
特征测试的关键是「锁住现状」:哪怕现状是错的,也先记录下来,避免重构时无意改变行为。
大重构失败的原因通常是「一次性替换」,而不是方向错误。
具体怎么做
按顺序执行,每步都验证完再进下一步:
- 挑一个边界清晰的小模块作为试点
- 为它的输入输出写特征测试(含异常路径)
- 提取接缝:把外部依赖抽成接口,便于替换
- 新实现并行运行,比对结果一致后切流量
- 删除旧代码,清理开关
参数与成本对照
把关键数值摊开,方便判断该选哪条路:
| 手段 | 作用 | 风险 |
|---|---|---|
| 特征测试 | 锁定现状行为 | 误把 bug 也锁住 |
| 绞杀者模式 | 渐进替换 | 双跑期资源翻倍 |
| 功能开关 | 快速回滚 | 开关长期不清理 |
| 小步提交 | 便于二分定位 | 需要纪律 |

几个容易踩的坑
下面这些是最常见的错误做法:
- 重构同时改需求:出问题无法判断是哪边引起
- 没有测试就大改结构
- 一次性替换所有调用点
- 开关留了两年不删
最后补两句
重构的安全感来自「可回滚」,而不是「想得周全」。
工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。
评论 (3)
照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。
比「一键脚本」有用多了,知道为什么比知道怎么做重要。
补充一句:不同版本行为会变,动手前先确认自己的版本号。
发表评论