AI 修复重复缺陷时,应先找齐所有调用点
文章指出,编程智能体容易围绕报错文件做局部修补,遗漏复制到其他位置的同类缺陷。建议先搜索所有相关逻辑,再判断是否提取共享函数,避免仅凭单一路径测试通过就结束修复。
AI 深度解读
AI 编程里有一种容易被测试通过掩盖的漏修:Agent 修好了报错的接口,同一段逻辑在其他文件里的副本却原封不动。下一个接口出错时,它又重新推导一遍答案。
作者给出的处理顺序是:先找全同类实现,再判断该统一到共享函数,还是直接交给框架,最后验证所有调用点。这篇没有实验数据,但提出了一个实用的审查问题:眼前修掉的是一个位置,还是一整类缺陷?
为什么一个测试变绿,还不能说明修完了
Agent 接到的任务通常带着明确的位置:某个文件、某个接口、一条失败测试。围绕这些证据做最小修改,可以迅速消除当前错误;问题在于,这个过程默认了缺陷只存在于此处。
真实代码库经常不满足这个前提。校验规则可能被复制到多个 handler,重试逻辑可能分散在几个客户端,处理某类响应的解析代码也可能到处都有。报错位置只是其中一份副本,其他副本没有被当前测试执行,自然不会暴露。
作者强调,局部缺陷与重复模式造成的缺陷,在报错现场看起来可能完全一样。仅检查当前文件,无法判断自己面对的是哪一种。
测试变绿,只能证明它覆盖的行为通过了,不能证明其他副本已经修复。
因此,作者建议把可能源于复制的缺陷暂时当作一类问题处理,直到仓库中的代码足以证明它确实局限于一处。这不是要求每次修错都重构整个项目,而是先确认修改范围,别让报错文件替你决定范围。
先找逻辑的形状,再决定怎么统一
找副本时,搜索变量名或整段字符串只是起点。复制出去的代码会慢慢变化:有人改了命名,有人调整了格式,还有人补了一个分支。字面搜索可能漏掉这些实现,但它们仍然保留着相似的处理步骤。
作者建议寻找「结构特征」。用大白话解释,就是看代码按什么顺序执行什么操作,而不只看它用了哪些名字。例如检查同一种解析过程,就要关注输入如何进入解析、结果如何被读取、异常如何被处理。
不过,原文没有给出结构查询工具、命令或查询示例,也没有展示搜索准确率。这是一项工作要求,还不是可以直接复制执行的搜索方案。实际操作仍需要结合搜索结果阅读代码,判断相似实现是否遵循同一条规则。
找到所有位置之后,作者给出三种处理方向:
- 同一套逻辑存在多份时,优先抽成一个有测试的共享单元,让所有调用点使用它,再在其中修复缺陷。
- 已经有共享函数时,把仍在使用内联副本的调用点接过去,避免继续维护两套实现。
- 框架或标准库已经负责这件事时,删除重复的手写实现,改用已有机制。
第三种容易被忽略。团队有时会认真修好每一份代码,却没再问一句:这些代码是否还有保留的必要?
作者看重共享实现,是因为逐份修补虽然能解决当前错误,却保留了未来再次分叉的条件。下一次规则调整,只改其中一份的情况还会重演。
让 Agent 交付覆盖证据,而不只是补丁
按照原文的思路,给 Agent 的验收要求应该包含三件东西:完整的同类实现清单、每个调用点的处理结果,以及针对共享行为的测试。
这三者分别回答不同的问题。清单说明搜索范围;调用点结果说明哪些位置已经统一、哪些仍有独立实现;共享测试说明修复后的规则是什么。
只有最初失败路径的测试,证明力比较有限。它可能在共享逻辑仍然错误时,因为某个调用点加了特殊处理而通过。测试共享行为,则能把规则固定在真正负责它的模块上,让后续修改有明确的检查对象。
这里还需要区分两个边界:共享测试通过,不等于所有调用点已经接入;所有调用点接入,也不等于共享规则正确。作者要求同时检查清单、接入情况和测试,就是要补上这些空隙。
我的判断
我认同作者对验收范围的提醒。AI 修复中容易遗漏的,并不总是补丁内部的错误,也可能是补丁之外仍然存在的同类代码。把「搜索其他实现」写进任务,比指望 Agent 自动理解整个仓库更可靠。
但原文没有提供具体仓库、修复记录、漏修比例或与其他方案的对照数据。因此,关于 Agent 通常如何行动、抽取共享函数能带来多大收益,都应视为经验判断,不能当作经过量化验证的结论。
「优先抽共享函数」也有前提:这些调用点确实遵循同一个业务契约。代码长得相似,不代表它们以后必须一起变化。若不同接口有意采用不同规则,强行合并可能引入大量条件参数,反而增加维护成本。逐份修复在这种情况下可以成立,但应明确保留差异的原因。
另外,统一实现减少了重复维护,却不能保证新副本永远不会出现。共享测试约束的是共享模块,后续新增的内联实现仍可能绕开它。原文对此的保证说得偏满。
能拿来做什么
- 给 Agent 派修复任务时,加上明确要求:修改前列出仓库内同类逻辑的位置,并说明哪些属于同一规则,哪些存在业务差异。
- 修复 Node handler 中的重复校验或客户端重试逻辑时,先检查已有共享模块;确认契约一致后,让相关调用点统一接入。
- 审查补丁时,把同类实现清单与实际改动逐项核对,并检查测试是否覆盖共享规则,以及原报错路径是否确实使用了它。
- 遇到手写解析、校验等重复代码时,检查框架或标准库是否已有对应机制;确认行为符合需求后,再决定是否删除手写副本。