开篇
看到一段难维护的代码时,你会不会马上想重构?
很多开发者的第一反应是:
方法太长
↓
类太大
↓
命名太乱
↓
赶紧拆分和重写
这件事本身没有错。
问题在于,代码“看起来不舒服”,并不等于现在就值得重构。
一段代码可能确实存在设计问题,但它也可能:
- 很少被调用。
- 即将被下线。
- 没有稳定测试。
- 依赖复杂的历史数据。
- 与多个系统存在隐式约定。
- 正处于高频变更期。
- 重构收益小于验证和回归成本。
如果没有先做评估,重构很容易变成一次高风险的大范围改动:
原本想改善结构
↓
顺手修改业务逻辑
↓
影响多个调用方
↓
测试无法证明没有回归
↓
维护成本反而更高
上一篇文章,我们讨论了如何让 AI 辅助写单测,重点是覆盖边界,而不是凑覆盖率。
重构前的第一件事,也不是让 AI 直接改代码,而是先确认:
这段代码真的值得改吗?如果值得,应该改到什么范围?
这篇文章分享一套我会使用的 AI 重构前评估流程,帮助你把“想重构”变成一个可以判断、可以验证、可以控制风险的工程任务。
本文不会讨论什么
重构前评估不是给代码打分,也不是让 AI 按照某种风格把整个项目重新写一遍。
本文不会:
- 认为方法超过几十行就一定需要重构。
- 认为使用设计模式越多,代码就越好。
- 建议为了追求整洁而扩大修改范围。
- 把 AI 的重构建议直接当成最终方案。
- 用静态复杂度指标代替业务影响和维护成本判断。
本文关注的是一套更谨慎的思路:
确认问题
↓
评估收益
↓
识别风险
↓
限定范围
↓
确认验证方式
↓
再决定是否重构
一、重构前先问:这段代码到底有什么问题
“代码很乱”不是一个足够具体的问题。
在让 AI 评估之前,我会先把问题拆成几类。
1. 理解成本高
表现为:
- 新开发者很难找到入口。
- 方法名和实际行为不一致。
- 业务规则隐藏在多层条件判断中。
- 同一个概念在不同地方使用不同名称。
2. 修改成本高
表现为:
- 修改一个规则需要改很多文件。
- 一个方法承担多个完全不同的职责。
- 相同逻辑在多个模块重复实现。
- 调用方无法明确知道方法的副作用。
3. 测试成本高
表现为:
- 很难构造测试数据。
- 必须启动大量外部依赖才能验证。
- 一个小改动会导致大量无关测试失败。
- 关键分支没有稳定的自动化测试。
4. 运行风险高
表现为:
- 异常处理不清晰。
- 事务边界不明确。
- 并发行为不可预测。
- 日志和监控无法定位问题。
- 性能已经出现可观察的瓶颈。
5. 业务变化频繁
表现为:
- 相关需求持续增加。
- 当前代码已经频繁修改。
- 多个团队都需要复用这段能力。
- 当前结构已经阻碍新功能交付。
只有先把问题说清楚,AI 才能判断“重构收益”而不是单纯指出风格问题。
二、不是所有难看的代码都值得重构
我会把待评估代码分成四种情况。
| 类型 | 典型特征 | 建议 |
|---|---|---|
| 高收益高频区 | 高频调用、频繁修改、问题持续发生 | 优先评估重构 |
| 高风险核心区 | 资金、权限、数据一致性和核心交易 | 小步重构,先补测试 |
| 低频遗留区 | 很少调用,短期没有需求 | 通常不要主动重构 |
| 即将下线区 | 已有替代方案或明确下线计划 | 不要投入大规模重构 |
代码质量问题和重构优先级不是一回事。
一段最丑的代码,可能不是最值得改的代码。
一段看起来还能工作的代码,如果每天都被修改、每次修改都引发回归,反而更值得优先处理。
三、让 AI 先做代码影响范围分析
重构前,我不会先问:
请帮我重构这个类。
我会先让 AI 分析它影响了什么。
请先不要重构代码,只分析下面这个类或模块的影响范围。
请输出:
1. 主要职责。
2. 对外暴露的接口。
3. 直接调用方。
4. 直接依赖的模块、数据库、缓存和外部服务。
5. 可能被依赖的隐式行为。
6. 关键副作用。
7. 相关测试和配置。
8. 如果修改它,最可能影响哪些功能?
请区分:
- 可以从代码直接确认的事实。
- 基于命名或结构的推测。
- 需要通过测试、日志或运行环境确认的内容。
不要给出重构方案。
这一步的目的是先画出“影响地图”。
例如,AI 可能发现一个看似普通的 calculatePrice() 方法,实际上被以下地方使用:
- 下单接口。
- 购物车预览。
- 订单重试任务。
- 对账脚本。
- 管理后台手工修复工具。
如果你只看当前调用方,很容易误判修改范围。
四、判断重构收益:它能解决什么问题
重构不是为了让代码看起来更漂亮,而是为了降低未来成本。
可以让 AI 按收益维度分析:
请评估重构这段代码可能带来的收益。
请从以下角度分别说明:
1. 是否降低理解成本。
2. 是否降低后续修改成本。
3. 是否减少重复逻辑。
4. 是否提高测试可行性。
5. 是否改善错误处理和可观测性。
6. 是否解决已经发生过的线上问题。
7. 是否支持近期确定的业务变化。
每项请区分:
- 当前已经存在的收益。
- 可能但尚未证明的收益。
- 仅属于代码风格改善的收益。
一个有价值的重构目标,最好能够落到具体结果:
重构前:
新增一个订单状态需要修改 5 个条件分支。
重构后:
订单状态规则集中在一个策略模块,并且每种状态都有独立测试。
或者:
重构前:
一次支付失败后无法判断是否已经扣款。
重构后:
支付结果、重试状态和补偿状态有明确的状态模型。
“代码更优雅”可以是附带收益,但不应该是唯一目标。
五、判断重构风险:哪些地方最容易出问题
重构风险通常不只来自代码量。
我会重点检查下面这些方面。
1. 行为变化风险
虽然目标是“不改变行为”,但重构可能意外改变:
- 默认值。
- 条件判断顺序。
- 异常类型。
- 返回值为空还是抛异常。
- 状态流转顺序。
- 边界时间处理。
2. 调用方兼容风险
需要确认:
- 方法签名是否被多个模块使用。
- 返回对象是否被外部系统依赖。
- 是否有未被静态搜索发现的反射、脚本或配置调用。
- 是否有历史接口兼容要求。
3. 数据风险
重点看:
- 数据库读写顺序。
- 事务边界。
- 缓存更新时机。
- 消息发布顺序。
- 数据迁移和历史数据兼容。
4. 性能风险
重构后可能出现:
- 查询次数增加。
- 循环中调用外部服务。
- 缓存失效。
- 对象创建和序列化增加。
- 批处理变成逐条处理。
5. 发布和回滚风险
需要确认:
- 是否可以灰度发布。
- 是否可以通过开关控制。
- 新旧逻辑能否并行验证。
- 回滚代码是否会与数据库结构不兼容。
- 是否需要补偿已经产生的数据。
可以让 AI 专门做风险审查:
请不要提供重构代码,只分析这段代码的重构风险。
请按以下类别输出:
1. 行为变化。
2. 调用方兼容。
3. 数据一致性。
4. 事务和并发。
5. 性能和资源。
6. 安全和权限。
7. 发布、灰度和回滚。
每个风险请说明:
- 触发条件。
- 可能后果。
- 当前是否已有测试或监控。
- 最小验证方法。
- 风险等级。
六、没有测试的核心代码,不适合直接大改
很多重构事故的根本原因不是重构方案错误,而是没有“行为保护网”。
如果一段核心代码没有测试,AI 无法可靠判断:
- 当前行为是否是故意的。
- 某个奇怪分支是否承载历史兼容。
- 哪些异常是调用方依赖的。
- 哪些边界是产品规则而不是偶然实现。
因此,重构前通常有两条路径:
已有足够测试
↓
评估并小步重构
或者:
没有足够测试
↓
先补行为基线测试
↓
再开始重构
可以让 AI 先帮你建立“重构前基线测试”:
请根据当前代码和已有业务行为,设计重构前的基线测试。
目标不是评价当前实现是否优雅,而是记录重构前已经存在的可观察行为。
请覆盖:
1. 正常输入和返回结果。
2. 边界输入。
3. 异常类型和错误信息。
4. 数据库、缓存、消息和外部调用。
5. 关键状态流转。
6. 已知线上问题和历史兼容行为。
先输出测试场景和风险,不要生成测试代码。
基线测试不代表当前行为一定正确。
它只是帮助你在重构后确认:
哪些行为保持不变
哪些行为是有意改变
哪些行为需要重新确认
七、哪些代码通常应该谨慎触碰
下面这些代码不是绝对不能重构,但需要更高的证据和更小的步子。
1. 资金和支付相关代码
重点风险:
- 重复扣款。
- 状态不一致。
- 超时结果未知。
- 重试和补偿行为改变。
2. 权限和安全边界
重点风险:
- 权限判断顺序改变。
- 列表和批量接口绕过校验。
- 敏感字段暴露。
- 内外部身份边界混淆。
3. 数据迁移和历史兼容代码
重点风险:
- 老数据无法读取。
- 新旧版本不兼容。
- 回滚失败。
- 重复迁移或数据丢失。
4. 消息消费和异步任务
重点风险:
- 重复消费。
- 顺序改变。
- 重试次数变化。
- 死信和补偿逻辑丢失。
5. 线上问题刚修复的代码
如果一段代码刚刚修复过线上事故,不建议马上做大规模结构调整。
更稳妥的顺序是:
先保留回归测试
↓
确认线上指标恢复
↓
记录当前行为和风险
↓
拆成小步重构
八、重构前让 AI 比较 3 种方案
重构不只有“改”和“不改”两个选项。
通常可以比较:
方案 A:保持现状,只补测试和注释
方案 B:局部重构,保持接口不变
方案 C:重新设计模块边界和接口
可以使用下面的 Prompt:
请针对下面的代码问题比较三种处理方案:
方案 A:不改变结构,只补测试、日志或注释。
方案 B:局部重构,保持现有对外接口不变。
方案 C:重新设计模块边界和调用方式。
请从以下角度比较:
1. 能解决哪些问题。
2. 不能解决哪些问题。
3. 代码影响范围。
4. 测试和验证成本。
5. 发布和回滚难度。
6. 对性能、数据和兼容性的影响。
7. 适合当前阶段的前提。
最后给出推荐方案,但不要默认“结构变化最大”的方案最好。
很多时候,方案 A 或方案 B 才是当前最合理的选择。
九、用“重构决策表”代替凭感觉决定
我会把 AI 的评估结果整理成一张决策表:
| 评估项 | 结论 | 证据 | 影响 |
|---|---|---|---|
| 修改频率 | 近三个月频繁变更 | 提交记录 | 重构收益较高 |
| 调用范围 | 被 6 个模块使用 | 代码搜索 | 兼容风险较高 |
| 测试覆盖 | 核心分支缺少测试 | 测试报告 | 需要先补基线 |
| 线上影响 | 最近出现数据不一致 | 事故记录 | 需要优先修复行为 |
| 下线计划 | 暂无 | 产品确认 | 可以考虑中期重构 |
| 回滚能力 | 可灰度、可开关 | 发布配置 | 风险可控 |
最后形成明确结论:
当前不建议做大规模重构。
建议先:
1. 补充核心行为测试。
2. 抽出重复的价格计算逻辑。
3. 保持现有接口和数据结构。
4. 通过灰度验证新旧结果一致。
5. 等下一次业务迭代再评估模块级重构。
这比“这段代码太乱,应该重写”更容易获得团队共识。
十、一个可以直接复用的重构前评估 Prompt
请作为一名谨慎的高级开发者,帮助我评估是否应该重构下面的代码。
一、当前问题
<描述为什么想重构,以及已经观察到的具体问题>
二、业务背景
<说明代码对应的业务功能、重要程度和近期变化>
三、项目上下文
<填写技术栈、模块边界、数据库、缓存、消息、外部依赖和发布方式>
四、代码和调用关系
<填写待评估代码、调用方、被调用方和相关测试>
五、变更约束
- 允许修改:
- 不允许修改:
- 必须保持兼容的接口:
- 不能接受的数据或行为变化:
请先不要写重构代码,按以下顺序完成评估:
1. 总结当前代码的真实职责。
2. 列出已经确认的问题。
3. 区分结构问题、行为问题和业务问题。
4. 分析重构可能带来的收益。
5. 分析行为、数据、性能、兼容、安全、发布和回滚风险。
6. 找出直接调用方、间接调用方和隐式依赖。
7. 检查现有测试是否足以保护当前行为。
8. 比较“不重构、局部重构、整体重构”三种方案。
9. 给出推荐方案和推荐前提。
10. 输出最小可行重构范围。
11. 列出重构前必须补充的测试和验证。
输出要求:
- 不要把个人代码风格偏好当成重构理由。
- 项目事实、代码推断、待确认项分开输出。
- 所有风险都要说明触发条件和验证方式。
- 优先推荐可回滚、可灰度、小步迭代的方案。
- 如果当前不值得重构,请明确说明“不建议重构”的理由。
这份 Prompt 最重要的一句话是:
如果当前不值得重构,请明确说明“不建议重构”的理由。
让 AI 有权给出“不改”的结论,评估结果反而更可信。
十一、重构开始后,如何让 AI 控制修改范围
当决定重构后,也不要直接让 AI “优化整个模块”。
可以继续限定:
请根据已经确认的重构范围,设计第一步最小修改。
要求:
1. 保持对外接口不变。
2. 不改变业务规则和返回结果。
3. 不修改数据库结构。
4. 不同时处理无关代码风格问题。
5. 每次只移动或拆分一个明确职责。
6. 给出修改前后的行为对照。
7. 给出必须执行的测试。
8. 如果发现范围会扩大,请先停止并列出原因。
重构过程中要尽量保持:
小步修改
↓
运行测试
↓
查看 Diff
↓
确认行为
↓
再进入下一步
如果一次改动跨越太多职责,就很难判断到底是哪一步引入了问题。
十二、我的重构前检查卡
[ ] 我能具体说清楚当前代码的问题
[ ] 我知道这段代码被谁调用
[ ] 我区分了结构问题、行为问题和业务问题
[ ] 我知道重构能带来什么实际收益
[ ] 我评估了数据、事务、并发、性能和兼容风险
[ ] 我确认了是否存在隐式调用和历史行为
[ ] 核心代码已有足够测试,或已经设计基线测试
[ ] 我比较过不重构、局部重构和整体重构
[ ] 我明确了允许修改和不允许修改的范围
[ ] 我优先选择可回滚、可灰度和小步迭代方案
[ ] 我没有把代码风格偏好当成重构理由
[ ] 每一步重构后都会执行测试并检查 Diff
如果无法回答“为什么现在要改”和“如何证明改对了”,就不应该急着开始重构。
十三、总结
重构不是代码越多改得越好,也不是结构变化越大越有价值。
真正值得重构的代码,通常具备这些特征:
- 高频修改并持续产生维护成本。
- 结构问题已经影响需求交付。
- 线上风险可以被明确描述。
- 重构收益能够被验证。
- 有测试、监控或灰度手段保护行为。
需要谨慎触碰的代码,通常包括:
- 资金、支付和核心交易。
- 权限和安全边界。
- 数据迁移和历史兼容。
- 消息消费和异步任务。
- 刚刚修复线上问题的关键逻辑。
我会坚持这套节奏:
先确认问题
↓
再评估收益
↓
识别影响和风险
↓
补充行为测试
↓
比较不同方案
↓
小步开始重构
请记住:
最成熟的重构判断,不是知道怎么改,而是知道什么时候不该改。
下一篇文章,我们继续解决开发工作中的另一个高频任务:
我如何让 AI 帮我写技术文档,而不制造废话。
如果这篇文章对你有帮助,欢迎点赞、收藏、关注专栏。
也欢迎在评论区留言:你遇到过哪些“看起来应该重构,但最后决定不动”的代码?
✍坚持原创,求关注,点赞,收藏