拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ChatGPT、Codex工程方法:旧项目准备大重构,为什么第一步反而是先锁定“行为基线”?

ChatGPT、Codex工程方法:旧项目准备大重构,为什么第一步反而是先锁定“行为基线”?

最近用 ChatGPT、Codex 接手旧项目时,我越来越不建议第一句话就是:

“帮我把这个模块重构一下。”

尤其是那种已经跑了三五年、代码风格很乱、测试又不完整的项目。

表面看起来,最值得做的是:

拆大类。

改命名。

抽公共逻辑。

调整目录。

重写接口。

把历史遗留代码全部整理一遍。

Codex做这些事情确实很快。

但真正危险的地方也在这里:

代码可以很快变漂亮,系统原来那些没人写进文档里的行为,也可能一起被改掉。

比如一个旧订单接口。

你看代码的时候觉得特别不合理:

订单不存在时居然返回200。

某个字段明明没有值,却返回空字符串而不是null。

重复提交时不报错,而是直接返回第一次结果。

某个状态明明已经废弃很多年,旧客户端却还在使用。

从“代码设计”角度看,这些都很想顺手改掉。

但问题是:

它们可能早就变成了真实系统的一部分。

所以旧项目大重构之前,我现在更关注的第一件事不是:

“怎么改得更漂亮?”

而是:

“这个系统现在实际上是怎么工作的?”

这就是:

Behavior Baseline——行为基线。


一、旧代码最危险的地方,不是乱,而是“没人知道哪些乱不能动”

一个成熟旧项目里,通常同时存在三种东西。

第一种:

真正的技术债。

比如重复代码、糟糕命名、不合理的依赖。

第二种:

历史兼容行为。

看起来不好看,但外部系统已经依赖。

第三种:

没人解释得清的特殊逻辑。

比如:

if amount == 0: return success

你可能觉得这段完全多余。

但继续查才发现:

三年前有一批历史订单就是靠这条逻辑兼容。

如果Agent一上来就按照“最佳实践”重写,

最容易把第二类和第三类一起当成第一类处理。

这也是为什么:

Cleaner Code ≠ Safer Refactor

代码更干净,

不代表重构更安全。


二、为什么Agent特别容易在旧项目里“改对代码,却改错行为”?

因为 ChatGPT、Codex 最容易看到的是:

当前代码结构。

类型定义。

调用关系。

测试。

但旧项目真正的行为契约,往往散落在:

线上数据。

客户端调用方式。

历史接口响应。

数据库副作用。

消息事件。

配置。

甚至运营人员的使用习惯里。

如果这些没有明确给出来,

Agent很自然会认为:

当前代码就是全部真相。

于是它可能主动修掉一些“看起来不合理”的地方。

比如把:

200 + error message

改成标准的:

404

从HTTP设计角度看,可能更合理。

但如果旧客户端只判断200:

线上立刻出问题。

所以旧项目重构真正难的不是:

Agent不会写新代码。

而是:

旧系统的真实契约往往没有被显式记录。


三、所以第一步不是Refactor,而是Characterize

重构前我更推荐先做:

Characterization——行为刻画。

简单说就是:

先把系统现在的关键行为记录下来。

不是先判断:

“这样设计对不对”。

而是先确认:

“现在它确实就是这么工作”。

例如一个旧接口可以先记录:

  • 正常输入返回什么;
  • 空数据返回什么;
  • 非法参数返回什么;
  • 会写哪些数据库表;
  • 会不会发消息;
  • 重试会不会产生重复副作用;
  • 历史数据怎么处理;
  • P95大概多少;
  • 哪些旧客户端仍然依赖。

这些东西加起来,才是真正的:

行为基线。


四、Characterization Test和普通单测不完全一样

普通单测经常表达的是:

“代码应该怎么工作。”

而Characterization Test更接近:

“代码现在实际上怎么工作。”

这两者区别很重要。

例如当前系统:

订单不存在时返回:

HTTP 200 code = ORDER_NOT_FOUND

你可能觉得这不合理。

但重构前可以先把这个行为锁下来。

不是说以后永远不能改。

而是:

如果要改,必须明确知道自己正在改变兼容行为。

这样重构就从:

“无意识破坏”

变成:

“有意识变更”。


五、行为基线不只包括API输出

这是最容易缩窄的地方。

很多人想到Behavior Baseline,只想到:

接口返回值。

其实真实项目里至少还应该看几类。

API行为

状态码。

字段结构。

错误语义。

数据行为

写哪些表。

字段默认值。

事务边界。

历史数据兼容。

副作用

是否发消息。

是否调用第三方。

是否写缓存。

时序行为

同步还是异步。

先写库还是先发事件。

性能行为

某些核心链路能不能接受重构后的额外耗时。

因为有时候代码功能完全正确,

但从300ms变成3秒,

一样不能算成功重构。


六、先锁“必须保持”,再决定“允许改变”

旧项目重构最实用的一个动作是:

把行为分成两类。

第一类:

Must Keep

必须保持。

比如:

旧API兼容。

历史数据可读。

同一请求不能重复扣款。

第二类:

Allowed to Change

允许改变。

比如:

内部类结构。

方法命名。

模块拆分。

缓存实现。

这样Agent就不会把所有“现状”都当成必须永久保留。

也不会把所有“不好看”都当成可以随便改。

真正的重构自由应该是:

实现可以大改,关键行为不能偷偷变。


七、一个比较稳的重构流程

我现在更推荐让 ChatGPT、Codex 按这个顺序做:

Capture Current Behavior

先收集现有行为。

↓

Define Must-Keep Behavior

确认哪些行为必须保留。

↓

Refactor

再开始改实现。

↓

Compare

新旧结果对比。

↓

Accept

确认行为没有意外变化,再接受当前Change Set。

这个顺序和直接:

“读代码 → 重构 → 跑测试”

最大的区别是:

重构前已经有了比较对象。

否则测试一旦不完整,

你甚至不知道Agent到底改变了什么。


八、为什么旧项目测试越少,越应该先做行为基线?

很多人会觉得:

项目测试都没有,怎么做基线?

恰恰相反。

测试越少,越不能直接大改。

因为这个时候唯一能保护你的不是原来的Test Suite,

而是:

先补一批关键行为快照。

不需要一开始就把覆盖率补到80%。

只要先锁几个真正关键场景:

核心API。

核心数据写入。

关键异常。

关键副作用。

历史兼容。

就已经比裸重构安全很多。


九、可以让Agent先做“只读阶段”

复杂旧项目我比较喜欢先给Codex一个明确限制:

先不要修改代码。

先完成:

  1. 找核心入口;
  2. 列关键调用链;
  3. 识别外部依赖;
  4. 找关键副作用;
  5. 收集现有测试;
  6. 输出建议锁定的行为基线。

这样第一阶段的目标不是:

产出Diff。

而是:

产出对当前系统的理解。

确认以后再进入Write阶段。

这会明显减少:

刚读几个文件就开始大范围重构。


十、行为基线还能帮助Review

Agent一次改几十个文件以后,

单纯看Git Diff特别累。

但如果前面已经定义:

“这5个行为必须保持”

Review就简单很多。

你不再需要逐行确认所有代码。

而是优先验证:

这些关键行为有没有变化。

比如:

  • 老客户端还能不能调用;
  • 历史数据还能不能读;
  • 重复请求是否仍然幂等;
  • Event Schema有没有变化;
  • P95有没有明显恶化。

这相当于把Review从:

代码中心

变成:

行为中心。


十一、什么时候应该允许行为变化?

行为基线不是让旧项目永远不能改变。

如果某个旧行为本身就是Bug,

当然可以改。

但变化最好显式化。

比如:

OLD: 订单不存在 → HTTP 200 NEW: 订单不存在 → HTTP 404

然后明确:

哪些客户端需要升级。

何时切换。

如何灰度。

如何回滚。

这和Agent直接“顺手修正”是完全不同的。

前者是:

Planned Behavior Change

后者是:

Accidental Behavior Change

真正要防的是后者。


十二、给自己看一个指标:行为保持率

这篇只看一个指标:

Behavior Preservation Rate——行为保持率

可以简单理解为:

重构前确认必须保持的关键行为中,重构后仍然保持一致的数量 ÷ 必须保持的关键行为总数

例如重构前锁定10个关键行为。

完成以后:

9个保持一致。

1个在Review时发现已经变化。

那么:

行为保持率 = 90%。

对于关键兼容行为来说,

这个数字最好尽量接近:

100%。

因为这些本来就是你提前定义的:

不能被无意改变的部分。


十三、行为保持率低,先别急着继续重构

如果每改一轮:

老接口坏一个。

历史数据出一个问题。

消息格式又变化。

说明真正的问题不是:

Codex修改能力不够。

而是:

行为边界没有建立好。

这时候继续让Agent多改几个模块,通常只会增加Review成本。

更值得先回去补:

Behavior Baseline。

Characterization Test。

Must-Keep List。

再继续下一阶段。


十四、Plus和Pro怎么判断?

如果你的场景主要是:

偶尔接手一个旧项目。

做局部重构。

一次只改少量模块。

主要让 ChatGPT、Codex 帮你读代码、补Characterization Test、分析影响范围,

这种使用强度下,Plus通常已经够用。

真正值得先做的是:

把关键行为锁清楚,

而不是直接追求更大的AI容量。


如果你的实际工作已经变成:

长期维护大型旧项目。

一次重构涉及几十个文件、多个模块。

需要Agent持续分析、修改、跑测试、做行为对比、回归验证。

同时还有多个复杂Change Set排队,

这时候Pro会更适合。

因为更多任务容量可以真正用于:

长时间重构。

多轮验证。

大范围代码理解。

但前提仍然是:

Behavior Baseline先建立起来。

否则Agent改得越快,

你只是更快地失去:

“到底什么不能变”的判断能力。


最后

旧项目准备大重构,

为什么第一步反而不是改代码?

因为旧系统最危险的地方往往不是:

代码有多乱。

而是:

你已经不知道哪些行为其实不能动。

所以真正稳的重构起点应该是:

先观察。

先记录。

先锁定关键行为。

再开始改。

让 ChatGPT、Codex 先回答:

“这个系统现在实际上怎么工作?”

再回答:

“我们准备把它改成什么样?”

当Behavior Baseline存在以后,

重构才真正从:

把代码写得更漂亮

变成:

在不破坏关键行为的前提下,把系统改得更好。

这才是旧项目大规模Agent重构真正值得守住的第一条边界。

持续分享 Codex、大模型开发与 AI 编程实战内容。
长期深度使用各类代码大模型,也整理了
稳定的Plus/Pro会员订阅渠道,有需要可自取。

返回列表