AI修复混入整文件格式化,如何影响代码审查
一次空值修复只有 12 行逻辑变更,却因格式化产生了 412 行差异,导致核心修改被大量无关变化淹没。文章指出,历史文件格式不统一时,智能体自动运行格式化工具会增加审查负担和回归遗漏风险。
AI 深度解读
让 AI 修一个空值处理 bug,功能只改了 12 行,PR 却触及 412 行。测试通过了,但真正需要审查的逻辑被格式调整淹没。作者借这次经历提出一个实用规则:功能修复和格式整理应该分开提交。
这篇短文关心的不是代码够不够整齐,而是审查者能不能看清改动。对经常让 Agent 修改旧项目的程序员,这个问题直接影响一次修复是否容易验证,以及下一个回归是否容易被发现。
为什么只改一个函数,却动了半个文件
作者让 Agent 修复一个 900 行文件中的空值处理问题。4 分钟后,Agent 交出了函数内的 12 行修改,还有一个通过的测试。但它创建的 PR 触及了 412 行,其中另外约 400 行都在调整格式。
双引号换成单引号、补尾逗号、调整缩进、合并空行。真正的修复只是 12 个 diff 块中的一个,审查者得翻过另外 11 个格式或空白调整块,才能找到需要判断的逻辑。
作者把原因归结为 Agent 编辑后自动运行项目格式化工具。这个动作有一个隐含前提:文件原本就符合格式规则。遇到遗留代码、混合风格,或还没统一规范的项目,格式化工具便会把一次局部修复扩展成大范围改动。
这里需要区分证据:上述 PR 是作者报告的具体经历;「多数 Agent 会在编辑后运行格式化工具」则是作者的概括,原文没有提供调查数据,也没有说明使用了哪款 Agent 或格式化工具。
把修复和整理分开,才能看清行为变化
作者给了三条成本很低的规则。
第一,在任务里明确要求只修改行为,不做格式整理,也不运行会改写整个文件的格式化步骤。如果文件确实需要统一风格,就另开一个只包含格式调整的 PR。
第二,提交审查前先检查 diff 的范围。一个函数的修复,应该尽量对应一个函数的改动。如果一个 12 行的问题带来约 400 行变更,就应该退回去拆分,而不是默认审查者能从里面找到重点。这里的行数是异常信号,不是所有修复都必须遵守的硬性上限。
第三,先用审查工具的「隐藏空白变化」功能查看 diff,辅助定位真正的逻辑修改。作者还提醒,如果实际改动因此难以辨认,当前 PR 就不适合直接审查。
测试通过,只证明已运行的测试通过;清楚的 diff 才让人有机会判断测试之外的影响。
作者认为,更深一层的损失是 diff 大小失去参考价值:12 行修复和约 400 行格式整理混在一起,合并队列、CI 报告和变更日志并不能替审查者解释这些改动的区别。人要么为一个小修复付出大审查的精力,要么逐渐习惯跳过这些文件。
我的判断
我赞成把行为修改和格式整理拆开,尤其是在风格尚未统一的旧项目中。它保留了一个很有用的审查信号:改动范围是否与任务范围相称。
不过,原文没有给出拆分前后的审查耗时、缺陷率或对照实验。「这些规则能减少回归」目前属于有道理的经验判断,不能当成已经量化验证的效果。
「隐藏空白变化」也有边界。双引号改成单引号、增加尾逗号,都包含非空白字符,未必能被这个开关过滤掉;在空白具有语义的文件中,隐藏空白还可能遮住需要检查的内容。它适合辅助定位,不能代替拆分提交。
另外,作者把纯格式 PR 描述为几乎不用审查,这说得偏满。至少还要确认格式化工具的配置和版本符合项目约定,并检查结果是否真的只有预期的格式变化。
原文先建议独立 PR,最后又建议独立 commit,两者的效果并不完全一样:独立 commit 便于逐个查看,但合并后的 PR 总 diff 仍可能很大。需要把审查范围彻底分开的团队,独立 PR 更直接。已经统一格式的项目,则可以继续在编辑后运行格式化工具,因为触发大范围历史改动的前提通常已经消除。
能拿来做什么
- 给 Agent 修复旧项目的任务加上明确约束:只做本次行为修改,沿用附近代码风格,格式整理单独提交。
- 在前端或 Node 项目中,让 Agent 交付时说明功能改动位置、测试结果,以及是否产生额外格式变化,方便快速核对任务范围。
- 审查时先看文件和改动行数是否符合预期,再用隐藏空白功能辅助阅读;遇到大量引号、尾逗号变化,要求拆分后再审。
- 如果团队准备统一历史文件的格式,就安排独立 PR,并约定格式化工具及配置,让后续小修复保持小范围 diff。