跳到主要内容

26 篇博文 含有标签「code-review」

查看所有标签

“AI 让我这么做的”辩护:当代码审查悄然停止提出异议

· 阅读需 12 分钟
Tian Pan
Software Engineer

在 2026 年的代码审查(Code Review)讨论串中,最昂贵的一句话莫过于“这是 Agent 这么写的”。这并非因为它本身是错的——有时它确实没错——而是因为它终止了本该由此开启的对话。审查者输入一个问题,作者直接引用模型的推理作为回复,讨论在任何人真正开始争论这项变更之前就结束了。反对一个自信且谈吐得体的模型的社交成本,已经悄然高过了合并一个隐蔽 Bug 的成本,而大多数团队在未来两个季度内都无法在指标中察觉到这种权衡。

这不是一个关于 AI 写代码好坏的故事。它会写代码,其中有些还写得不错。这是一个关于当编写代码的摩擦消失时,质量关卡(Quality Gate)会发生什么的故事。审查速度上升,缺陷率也随之同步上升,而这种关联并不明显,因为没有人在追踪审查耗时与缺陷时会关联作者的类别。曾经是代码库品味核心的资深工程师,在一个悄然转向“模型盲从”的文化中,变成了孤独的坚持者。

Prompt 作者身份问题:三个角色同时编辑同一个文件

· 阅读需 14 分钟
Tian Pan
Software Engineer

翻开任何一个运行了一年的生产系统提示词(system prompt)的 git blame,你都会发现一些工程团队不愿承认的事实:这个文件有三个作者,而他们对“变更”的定义各不相同。上个月重构指令块的工程师将提交记录标为“无功能变更,仅为了清晰起见重新排序”。每季度读一次该文件的产品经理会这样描述同样的差异:“你改写了语气——客户会察觉到的”。运行回归测试套件的 ML 工程师会说:“你搞坏了第三个少样本示例(few-shot example),从那以后评估结果(eval)就一直变红了”。

这三者都是正确的。提示词同时具备代码、规范和超参数的属性。任何长期交付 AI 功能的团队都会发现,该文件的提交历史是一场缓慢进行的三方署名权争议,CODEOWNERS 无法捕捉到这一点,diff 查看器也无法体现出来。

混合 PR 队列:审查者吞吐量已成为瓶颈约束

· 阅读需 10 分钟
Tian Pan
Software Engineer

在过去的二十年里,制约理论(Theory of Constraints)在软件交付中的答案始终如一:瓶颈在于编写代码。我们围绕这一假设构建了一切——结对编程、IDE 自动补全、更快的 CI、更小的微服务,所有这些都是为了让更多的代码通过固定宽度的审阅管道。接着,编程 Agent 出现了,管道的生产端拓宽了 5–10 倍,而审阅管道的宽度却纹丝不动。一位过去每周提交 3 个 PR 的资深工程师,现在正监督着一群在一个下午就能提交 30 个 PR 的智能体。团队的交付速度不再取决于编写代码的速度,而是取决于人类阅读代码的速度。

这并非未来的问题。据测量,在某些样本中,PR 审阅时间的中位数同比增长了 441%,并且在未经任何审阅的情况下就被合并的 PR 增加了 31%——这并非出于政策规定,而是因为审阅者已经放弃了跟上进度。Stripe 每周交付超过一千个由 Agent 生成的 PR。在一项基准测试中,特性分支(feature-branch)的吞吐量同比增长了 59%,而主分支(main-branch)的吞吐量却下降了 7%——代码正在被编写,但没有被发布,因为它们卡在了审阅环节。

需求文档、代码、测试皆出自一人:你正在悄然失去的独立性

· 阅读需 12 分钟
Tian Pan
Software Engineer

当同一个模型负责编写需求、实现代码并编写用于验证正确性的断言时,“所有测试通过”不再是功能正常工作的证据,而仅仅证明了模型是内部一致的。这是两回事,而这种区别正是编写测试的初衷。

我们通常对测试套件的理解是,它们提供了“第二意见”。作者带着一种对需求的心理模型编写代码,而测试编写者则带着略有不同的心理模型编写断言。这两个模型不一致的地方,往往就是 Bug 潜伏之处。这种说法的前提是测试编写者与代码作者拥有不同的认知视角。如果去掉了视角的差异,测试套件就不再携带关于正确性的任何独立信息——它只携带关于一致性的信息。

Prompt 修改不只是措辞变动:将 Prompt 视为软件的代码审查规范

· 阅读需 13 分钟
Tian Pan
Software Engineer

周二下午,一个只有六行代码的系统提示词(system prompt)编辑出现在了一个 Pull Request (PR) 中。Diff 只是普通的英文。两位评审者扫了一眼新的措辞,觉得读起来更自然,于是点击了批准。PR 在不到一分钟内合并。到了周五,客服开始收到关于智能体的工单:它突然拒绝总结超过一定长度的文档,不再引用来源,并莫名其妙地在每句回复开头都加上 “Certainly!” —— 这种行为没人要求过,Diff 中也无法预见。

当一个花了十年时间学习如何评审代码的团队,在面对提示词这一产物时,竟然退化到了第一周的水平,结果就是这样。Diff 看起来 毫无害处,因为它读起来像英语,而人类正是用眼睛来审阅英语的。让代码评审发挥作用的规范 —— 运行测试、检查影响范围、对 “小改动” 保持适当的怀疑 —— 并没有悄然转化。措辞变好了,但行为变差了,直到用户发现之前,没人注意到。

AI 代码审查倒置:当作者是机器时应关注什么

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的代码评审正在优化错误的目标。当 AI 智能体(agent)贡献了你大部分的代码提交(commits)时,评审局部正确性——这个函数的功能是否如其所述?——就像是通过检查笔迹来给数学考试评分一样。机器已经通过了你的代码检查工具(linter),运行了你的测试套件,并按照规范格式化了输出。它所引入的 Bug 并不是行内(line-by-line)评审所能捕捉到的那种 Bug。

一项针对 GitHub Pull Request 的大规模研究发现,AI 协同编写的 PR 包含的缺陷是纯人工 PR 的 1.7 倍——其中包含多出 75% 的逻辑和正确性问题、2.74 倍的安全漏洞以及 3 倍的可读性问题。这并不是因为代码看起来有问题,而是因为它在错误的地方做了错误的事情,且对系统的其他部分持有错误的假设。这些恰恰是为捕捉拼写错误和风格违规而优化的传统代码评审所无法发现的故障模式。

隐形作者问题:当 AI 编写大部分代码时如何进行 Git Blame

· 阅读需 9 分钟
Tian Pan
Software Engineer

当生产环境出现故障时,工程师们首先会想到 git blame。提交哈希值指向 PR,PR 指向作者,而作者则指向上下文——Slack 讨论串、设计文档,或者是记住了代码初衷的那个大脑。这条链路是团队排查事故、进行安全审计以及积累机构知识的方式。它假设每一行代码都有一个理解自己在做什么的人类作者。

AI 已经悄然打破了这一假设。目前约 46% 的代码由 AI 生成,在 Java 团队中,这一比例甚至超过了 60%。这些代码中的大部分都不携带任何有意义的溯源元数据。git blame 链条依然在运转——只是现在它终止于一名开发者,他们接受了一个可能并未完全理解的建议,而且没有记录提示词、模型版本或 AI 拒绝的备选方案。

AI 数秒生成代码,团队却花数小时审查——这笔账根本不对

· 阅读需 9 分钟
Tian Pan
Software Engineer

AI 编程工具的 ROI 宣传在纸面上看起来无懈可击:在受控实验中,开发者完成任务的速度提升了 55%,合并的 Pull Request 数量增加了 98%,每周据称节省 3.6 小时。但当组织审视真实的交付指标——Bug 率、发布周期、故障频率——时,数字几乎没有任何变化。某些东西吸走了所有增益的时间,而它并不难找。

AI 数秒生成代码。工程师的审查速度,却和以前一样慢。

代码所有权衰减:当 AI 编写大部分提交时,团队知识会发生什么

· 阅读需 11 分钟
Tian Pan
Software Engineer

当生产环境出现 Bug 时,第一个仪式总是相同的:打开 git blame,找到写下那行代码的人,问他们为什么要这么写。这个仪式假设作者是有原因的——他们知道的某个限制、刻意处理的边缘情况,或者从三个季度的复盘报告中内化而来的业务规则。在软件史的大部分时间里,git blame 回答的是关于意图的问题。

现在,对于比例日益增长的提交,git blame 指向的是合并代码的人和生成代码的 AI。人类可能只花了 90 秒阅读 diff。而 AI 除了 prompt 之外没有任何上下文。那些让 git blame 变得有用的“为什么”——即组织知识——从未在任何地方被记录下来。

这就是代码所有权衰减。它不会自我宣告。没有哪一个单一的提交会破坏系统。相反,理解力会慢慢被掏空,直到团队到达一个决策点——一次重构、一次事故或一名新员工入职——才发现再也没有人能从内部解释这个系统了。

生产环境中的 LLM 代码审查:构建工程师真正信任的 Diff 流水线

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数部署 LLM 代码审查工具的团队都会在两周内发现同一种失败模式:模型为每个 PR 生成 10–20 条评论,其中 80% 都是噪音。在第三个 PR 中,如果开发者不看就关闭了所有评论,这个工具就名存实亡了 —— 通知被发送到无人查看的频道,而机器人仍然在每次推送时消耗算力。

问题不在于模型。而在于这些团队发布了一个评论生成器,却称之为审查工具。

你的编程智能体是一个从不阅读测试的初级工程师

· 阅读需 11 分钟
Tian Pan
Software Engineer

基准测试数据讲述了一个奇怪的故事。在 SWE-bench Verified 上,多个运行相同底层模型(均为 Opus 4.5)的智能体产品——Auggie、Cursor、Claude Code——产出了截然不同的结果。尽管“大脑”完全相同,Auggie 在 731 个问题中比最接近的对手多解决了 17 个。差距在于“脚手架”(scaffolding):智能体是如何被提示的、被赋予了什么上下文、可以调用哪些工具,以及在困惑时测试框架(harness)做了什么。模型是商品,围绕它的脚手架才是产品。

这是成熟的工程团队在十年前对初级工程师达成的相同共识。一个聪明的毕业生能交付价值,并非仅仅因为模型优秀,而是因为 README 是最新的,测试套件运行迅速,代码审查标准每次都能捕捉到那六个同样的错误,并且有人编写了说明约束条件的 CONTRIBUTING.md。剥离这些脚手架,同一个人产出的代码可能局部连贯但全局错误,破坏了团队甚至没想到要写下来的生产环境不变量。

将 Eval 作为 Pull Request 评论而非任务:在代码审查中嵌入 LLM 质量门禁

· 阅读需 12 分钟
Tian Pan
Software Engineer

许多自称“有评估(evals)”的团队,其实际情况是:有一个仪表板,某人每周运行一次测试套件,然后将数据粘贴到没人看的 Slack 频道。评审人员批准提示词(prompt)更改时,甚至根本没看过它是否影响了测试套件,而回归问题(regression)两周后才在客户反馈单中显现。评估确实存在,但评估并未进入开发循环。

解决办法在于结构,而非意愿。只有当评估存在于变更发生的地方——即 Pull Request(PR)评论中,紧挨着代码差异(diff),并带有单个 PR 的增量变化和评审员无法忽视的回归提醒时,评估才能真正起到质量把关的作用。在其他任何地方,它们都只是表演性的产物:投入了大量精力构建,却什么也拦截不到。