用 Codex 重构代码:替换旧实现,也要清理旧路径 - AIPlan

让 AI 重构时怎样避免新旧逻辑并存?先写行为约束和调用范围,小步替换重复实现,检查引用、依赖和回归结果。

用 Codex 重构代码:替换旧实现,也要清理旧路径 - AIPlan
重构失败最常见的形态不是改坏了,是改出了两套实现。旧函数还在,新函数也能用,调用方一半走旧的一半走新的。判断标准很直接:重构完成后,旧实现应该不存在于仓库里。截至 2026 年 10 月 18 日核对,这套做法在桌面版的审查面板和 CLI 上都能验证。 先写行为约束,再谈结构 重构改的是结构,不是行为。这句话说起来简单,落地要一份可验证的清单。开工前把现有行为列出来: 1. 传入空列表返回空数组,不报错 2. 金额大于 0 时四舍五入到 2 位 3. 优惠券过期返回 409,不是 400 4. 同一订单重复提交幂等,返回同一结果 4 条约束对应 4 个测试。这 4 条测试在重构前后必须都通过,且测试代码不动。测试被改动是重构失控的第一个信号。 如果项目现在没有这些测试,先补测试再重构。补测试的工作量通常是重构本身的 1 到 2 倍,省不掉。 摸清调用方再动手 改一个共享函数之前,先找出所有调用方。Codex 能做这件事,任务描述这样写: 只读任务。找出 formatPrice 函数在整个仓库的所有调用点, 输出文件路径、行号、调用方式,以及每个调用方传入的参数类型。 不要修改任何文件。 在实际项目里,一个看起来只被 3 个地方调用的工具函数,真实调用点常常是 11 个,其中 2 个是通过字符串拼接的间接调用,1 个在测试里用不同的参数签名。 漏掉调用方的代价是运行时报错,而不是编译时报错。Go 这类静态类型语言好一些,编译能拦住一部分;JS 和 Python 就只能靠测试和肉眼。 小步替换,每步可回退 一次改 300 行和分 5 次改 60 行,最终代码可能一样,但出问题时的定位成本差 10 倍。 推荐的节奏: • 第一步只改函数内部实现,签名不动 • 第二步改签名,所有调用方跟着改 • 第三步删旧函数 • 第四步清理旧函数留下的 import 和类型定义 每一步结束跑一次测试,打一个 Git 检查点。官方快速上手文档就建议在任务前后建检查点,重构场景里这条尤其值得照做。 第 3 步是很多人跳过的一步。旧函数删掉之前,新实现已经在用了,删掉是安全的;不删,三个月后有人看到两个函数,会挑那个“看起来更稳定”的旧版本用。 审查面板能看清动了什么 桌面版里输入 /review,选 Review uncommitted changes,它会按优先级报发现并且不改工作区。切换范围到 Last turn 只看上一轮助手的改动,重构时这个视图最有用。 面板默认显示 Unstaged,也可以切 Staged、Commit、Branch。重构涉及多个文件时,用 Branch 看和基线的整体差异,比逐个文件翻快。 一个必须知道的边界:审查面板反映的是整个 Git 仓库状态,包含你自己手改的部分。重构期间如果还在改别的功能,两批改动会混在一起。干净的做法是重构前 git stash 或者单独开分支。 审查该怎么要求发现格式,可以看 用 Codex 做代码审查:每个发现都要说明怎样触发,那套四行模板在重构场景里同样适用。 死代码怎么判定 删之前先确认三件事: • 全仓库搜不到引用,包括字符串拼接和配置里的函数名 • 没有外部包依赖它(如果是导出的公共 API) • 没有被动态加载的路径命中 第三条最容易被漏。一个 plugins/*.py 目录下的模块可能没有任何静态 import,但运行时会被扫描加载。让 Codex 找这类引用,任务里要写明“包括字符串匹配和配置文件”。 删完再搜一次,这次搜的是旧名字。搜不到才算删干净。这个动作花 30 秒,能避免“以为删了其实还有一份”的情况。 依赖和目录也要一起看 重构经常留下这些东西: • 只被旧实现用的第三方包,还在 package.json 里 • 只为旧实现存在的目录,里面 1 个文件 • 旧的类型定义,没人引用 让 Codex 清理时,任务描述可以点名:“删除旧实现后,检查 package.json 里是否有只被它使用的依赖,列出候选,不要直接删。”列出候选而不是直接删,是因为判断依赖是否可以移除需要看整个项目的运行路径,模型容易误删间接用到的包。 npm install -g @openai/codex 这类全局安装的版本也要跟着更新,Astra 需要 0.153.0 或更新,旧版本上某些模型选项不出现,重构时想对比两个模型的输出就会卡住。 回归检查的 3 个层次 重构后的验证分三层: 层次 检查什么 成本 单元测试 函数级行为是否一致 秒级 集成测试 跨模块调用是否还通 分钟级 手工冒烟 关键流程走一遍 10 分钟 三层都过才算完成。只跑单元测试的风险是:函数行为对了,但调用链上的参数转换错了,单元测试覆盖不到。 手工冒烟清单写 3 到 5 条就够,挑用户最常走的那条路径。比如“登录 → 选商品 → 下单 → 看到订单详情”,4 步走通,主干就没问题。 什么情况不该重构 三种情况建议先放着: • 这段代码 3 个月内要整个替换掉 • 没有测试覆盖且改动风险高于收益 • 你无法在 1 天内验证改动是否正确 第一条最常见。为一个下季度就废弃的模块做精细重构,投入的时间不会回来。 一次典型的规模和时间 改一个 400 行的工具模块,把 5 个重复函数合并成 1 个,典型的时间分配: • 补测试:90 分钟 • 找调用方:20 分钟 • 改实现:40 分钟 • 改调用方:30 分钟 • 删旧代码和依赖:15 分钟 • 三层验证:45 分钟 合计 4 小时。其中真正写代码的 70 分钟,其余 170 分钟都在准备和验证。这个比例是正常的,把它当成异常去压缩,压缩掉的通常是测试。 这种规模的重构用量消耗不大,读的文件集中在 1 到 2 个模块。Plus 的 $20 折算约 ¥133.80,一周做 2 到 3 次这种重构够用,¥115.50 的 Plus 月卡 是同样的 Codex 通道。跨 10 个模块的大重构才需要看 Codex 额度不够用时先看任务怎么消耗。 重构完把旧名字再搜一遍,搜不到,这件事才算结束。 参考资料资料核对日期:2026-10-17 • Codex CLI • Code review 延伸阅读• 用 Codex 做代码审查:每个发现都要说明怎样触发 • 让 Codex 写测试:先问这条测试能发现什么错误 • 给 Codex 下任务怎么写?让目标、边界和验收都可检查