Codex 改完代码,我不会先看写得漂不漂亮,而是先核对这 4 件事

Codex 改完代码,我不会先看写得漂不漂亮,而是先核对这 4 件事

前两篇完成了组件修改前的准备:先查调用链,再从用户行为、公开契约、状态、副作用和生命周期等层面划清影响范围。

现在 Codex 已经完成修改,终于到了看代码的时候。

这一步很容易陷入一个习惯:从第一行差异开始读,看看变量名好不好、函数拆得是否合理、写法是否优雅。

我现在不会这样开始。

AI 生成的代码往往足够像一份正常实现。命名完整、分支齐全、注释合理,甚至比原项目更整齐。如果审查从“写得像不像好代码”开始,我很容易顺着实现思路往下读,却忘了更重要的事情:

  • 这是不是我要求修改的那一组差异;

  • 每一处变化是否都能对应需求;

  • 原本要求保持不变的行为有没有被改变;

  • 所谓完成是否有真实证据。

所以我审查 Codex 的前端改动时,先核对 4 件事:

  1. 审查对象到底是哪一批差异;

  2. 每处修改为什么必须存在;

  3. 修改后的行为是否真的正确;

  4. 完成结论由什么证据支撑。

代码风格和局部写法要看,但它们不应该抢在任务正确性之前。

第一件事:先固定审查对象,不让差异范围含糊

“请审查刚才的修改”听起来很明确,在真实工作区里可能并不明确。

当前目录中可能同时存在:

  • Codex 本轮修改;

  • 我之前尚未提交的修改;

  • 格式化工具产生的变化;

  • 生成文件;

  • 其他任务留下的文件;

  • 暂存和未暂存的不同版本;

  • 新增但尚未跟踪的文件。

如果不先固定审查范围,我可能把用户原有改动误认为 AI 越界,也可能漏掉 Codex 新增但没有进入预期差异的文件。

OpenAI 的 Codex 代码审查文档把审查范围明确区分为相对基础分支、未提交修改、指定提交和自定义范围,并提醒审查视图反映的是仓库状态,不只包含 Codex 自己编辑的内容。

这对我最大的提醒是:

审查不是“看看现在有什么变化”,而是明确“当前结论针对哪一批变化”。

我会先记录四项范围信息

# 本次审查范围 - 对比基线: - 包含的文件: - 明确排除的已有修改: - 新增、删除、重命名和生成文件:

对比基线可以是任务开始前状态、基础分支、某个提交或本轮修改,具体取决于当前工作流。关键是审查结论和基线一致。

先看文件级变化,不急着钻进代码

我会先扫一遍:

  • 修改了多少文件;

  • 哪些是新增、删除或重命名;

  • 是否出现计划外目录;

  • 是否有大面积格式变化;

  • 是否有依赖、配置、锁文件或生成文件变化;

  • 是否存在任务说明里没有提到的公共模块。

这一轮的目标是发现“范围形状”异常。

比如任务只要求调整一个页面交互,差异里却出现公共请求层、全局样式和依赖锁文件。即使每一处改动都有解释,我也会先暂停,要求说明它们为什么是完成当前目标的必要条件。

第二件事:把每处差异映射回任务目标

固定范围后,我不会立刻评价实现好坏,而是先问:

这一处变化对应哪个需求结果?

我会把差异分成四类。

目标变化

直接实现用户要求的行为。例如新增筛选入口、调整事件负载、处理失败恢复。

必要支撑

不是用户直接看到的结果,但为目标变化提供契约、类型、状态或验证支持。

兼容调整

为了保持既有调用方和旧行为,需要补充的适配。

无关变化

与当前目标没有必要关系的重命名、抽取、格式化、依赖升级、样式整理或技术债修复。

一份可信差异应该能解释前三类,并主动剔除第四类。

我使用一张差异映射表

文件或差异块变化类型对应目标为什么必要验证方式
页面入口目标变化用户可以触发新行为直接实现入口页面操作
组件事件类型必要支撑父页面取得新结果保持契约清楚类型检查与调用方检查
包装组件适配兼容调整上层调用继续工作事件需要透传包装链回归
无关工具函数重构无关变化当前任务不需要应移出本次差异

这张表能暴露两种问题。

第一种是遗漏:任务目标没有任何差异对应,说明实现可能只覆盖了部分路径。

第二种是越界:差异块找不到目标或必要支撑,只能用“顺手优化”解释。

第三件事:按行为路径检查正确性,不按代码顺序检查

逐行读代码当然重要,但前端正确性更适合沿用户路径检查。

我会先把任务拆成几条场景:

  • 正常路径;

  • 失败路径;

  • 边界输入;

  • 连续操作;

  • 关闭、返回和重新进入;

  • 权限或条件分支;

  • 与既有行为的回归路径。

然后沿每条路径读差异。

例如一个表单提交修改,我不会只看submit函数是否写得合理,而会沿下面的顺序看:

用户输入 → 校验 → 按钮状态 → 请求参数 → 成功处理 → 列表或详情刷新 → 关闭与清理

失败路径则是:

用户输入 → 校验通过 → 请求失败 → Loading 恢复 → 输入保留或恢复 → 错误反馈 → 是否可重试

代码可能分散在页面、组件、状态和请求层,但用户路径是连续的。

正确性不等于“代码能执行”

我会检查:

  • 状态来源是否仍然唯一;

  • 参数转换是否符合接口契约;

  • 事件触发时机是否与调用方一致;

  • 成功和失败是否对称收尾;

  • 旧请求是否可能覆盖新状态;

  • 默认值和空值是否改变含义;

  • 权限和可见性是否在正确层处理;

  • 关闭、卸载和返回时是否残留状态。

类型正确、语法正确和构建通过,只能覆盖其中一部分。

把“看起来合理”换成可反驳的问题

比如不要只问:

这个 Loading 处理合理吗?

而是问:

  • 请求失败时它在哪个分支恢复?

  • 连续点击是否可能产生第二次请求?

  • 关闭弹窗后请求返回,会更新哪一份状态?

  • 同一页面的其他动作是否共用这个 Loading?

问题越具体,越容易找到差异中的真实缺口。

第四件事:检查完成证据,而不是接受实现说明

Codex 的交付说明可能会列出:

  • 已增加某功能;

  • 已处理某边界;

  • 已运行某检查;

  • 已完成相关修改。

这些是过程陈述,不自动等于完成证据。

我会把证据分成五类:

差异证据

实际修改是否与计划和影响范围一致,有没有计划外文件和无关变化。

静态证据

类型、Lint、构建和其他项目检查是否运行,它们覆盖哪些文件和规则。

测试证据

哪些已有测试运行,哪些新增或调整;测试证明了哪个行为,哪些路径仍未覆盖。

页面证据

目标页面是否真实运行,正常、失败、连续操作和生命周期路径是否验证。

未验证说明

当前环境无法确认什么,为什么无法确认,需要谁在什么条件下继续检查。

如果 Codex 只说“测试通过”,我还会问:运行的是什么测试、是否覆盖本次变化、有没有跳过、失败后是否修正并重新运行。

完成结论只能覆盖证据实际到达的范围。

我审查一批前端差异的顺序

把前面四件事连起来,我通常按下面顺序执行。

第一步:恢复任务基线

重新读取目标、允许范围、禁止项、调用链、影响范围和验收标准。

没有基线,审查只能变成个人代码偏好。

第二步:固定差异范围

确认对比基线、文件状态、新增删除以及与用户已有改动的边界。

第三步:扫文件级异常

查计划外文件、公共模块、依赖配置、大面积格式化和生成内容。

第四步:建立目标映射

让每个需求结果对应到差异,让每个差异说明存在理由。

第五步:沿行为路径读代码

先正常、失败和边界,再检查连续操作、生命周期和回归。

第六步:复查完整差异

局部修正以后重新看全量,防止不同修改块组合后产生新问题。

第七步:核对验证证据

明确已通过、未通过和未验证,不能用实现完成代替验收完成。

一个方法演示:为什么局部正确仍然可能整体错误

下面仅用于说明审查思路,不代表真实项目经历。

假设目标是:保存成功后刷新当前列表,并保留筛选条件和页码。

Codex 修改了弹窗组件:

  • 保存成功后触发事件;

  • 关闭弹窗;

  • 重置表单;

  • 父页面收到事件后刷新列表。

每个差异块单独看都合理。

沿行为路径审查时,却可能发现顺序是:

保存成功 → 关闭并清理当前编辑对象 → 触发 saved 事件 → 父页面读取已被清理的上下文 → 刷新时回到默认查询状态

问题不在某一行语法,而在多个合理动作组合后的时序。

如果我只逐文件看“弹窗是否正确”“父页面是否正确”,很可能漏掉;沿完整用户路径看,问题会直接暴露。

审查意见也要有质量标准

我不会给 Codex 留这种意见:

  • 这里不够优雅;

  • 这个写法不太好;

  • 建议再优化一下;

  • 注意边界情况。

它们没有说明问题发生在哪里,也没有说明什么结果才算修好。

一条可执行审查意见至少包含:

问题 + 触发条件 + 影响 + 证据 + 修正边界

例如:

问题:关闭弹窗时先清理了当前记录,saved 事件随后才触发。 触发条件:保存成功且父页面依赖当前记录刷新局部数据。 影响:父页面拿不到正确标识,可能退回全量刷新或刷新错误对象。 证据:组件关闭分支与事件触发顺序,以及父页面监听逻辑。 修正边界:保持事件名称和父页面查询状态不变,只调整成功路径的触发与清理顺序,并回归失败和主动取消路径。

这样的反馈才能直接进入下一轮修正和验证。

哪些信号说明差异还不能接受

  • 审查基线不清楚;

  • 存在无法归属的新增文件;

  • 需求目标没有对应差异;

  • 差异只能用“顺手优化”解释;

  • 公共契约变化没有调用方检查;

  • 正常路径正确,失败和生命周期没有收尾;

  • 类型和构建通过,但页面行为未验证;

  • 修复一处后没有重看完整差异;

  • 交付说明把未运行的检查写成完成;

  • 无法区分 AI 修改与用户原有改动。

任何一项成立,我都会把任务保持在“待审查”或“待验证”,而不是因为代码已经写完就进入交付。

写在最后

我审查 Codex 的前端代码,不从“写得漂不漂亮”开始,而是先核对:

  1. 当前审查的是哪一批差异;

  2. 每处变化能否映射到任务目标;

  3. 正常、失败、边界和生命周期行为是否正确;

  4. 完成结论是否有对应证据。

代码审查不是欣赏实现,而是用任务基线反驳实现中的错误假设。

下一篇我会把这一套审查顺序压缩成一张前端差异检查清单,分别从正确性、修改范围和副作用三个层面列出具体问题,并给出审查结论和反馈模板。

本系列持续更新。接下来会用这张清单把“看代码”变成可重复执行的验收动作,为后面的静态检查、单测和页面验证分工做准备。

参考资料

  • OpenAI Codex 文档:代码审查范围、优先级发现和行级反馈

  • OpenAI Codex 用例:复杂任务应以可审查产物和评估方式推动迭代