剖析了『context-aware code review』在营销中被滥用的现象,辨析了 diff 级审查与真正的代码库理解的区别,讨论了上下文的多个维度。
如果你最近关注过 AI 代码审查工具,大概已经到处见过“上下文感知代码审查”(context-aware code review)这个说法。
似乎每款工具都在使用这个词。
有些工具强调对代码仓库的感知,有些声称能够理解整个代码库,还有少数工具宣称自己能够理解系统架构和工程最佳实践。
花了一些时间阅读文档、测试不同工具,并比较它们审查 pull request 的方式之后,我意识到了一件事:
我们大多数人其实并不真正清楚“上下文感知”究竟是什么意思。
这个词被使用得太频繁,以至于你很难判断一款工具是真的理解你的代码库,还是仅仅审查了 diff,然后把这种能力包装成了“上下文感知”。
所以,我想深入探讨一下代码审查中的“上下文”究竟意味着什么,以及它为什么重要。
无论审查工作由人类完成,还是由 AI 工具完成,起点通常都一样。
那就是 pull request 的 diff。
审查者会查看发生了哪些变更、修改了哪些文件、添加或删除了哪些代码,以及测试是否得到相应更新。
AI 审查工具通常也采用相同的工作方式。它们接收 diff,然后根据其中的变更生成反馈。
对于很多 pull request 来说,这样做完全没有问题。
如果你只是在修复一个拼写错误、更新一个工具函数,或者清理部分代码,那么 diff 往往已经包含审查这项变更所需的全部信息。
问题出现在变更会影响被修改文件之外的行为时。
这正是上下文开始变得重要的地方。
假设某个 pull request 中包含下面这行代码:
updatePaymentStatus(paymentId, status);
如果只看 diff,似乎没有任何问题。
看不出什么明显的异常。
但假设实际情况还包括以下几点:
支付服务应该在状态发生变化时发布一个事件。
出于合规要求,必须记录审计日志。
类似的更新流程还会同步更新元数据字段。
另一个服务依赖某个特定的副作用。
这些信息全都不会出现在 diff 中。
如果你熟悉这个系统,或许能立刻发现问题。
如果不熟悉,你大概就需要搜索代码仓库、查看类似的实现,并理解这段代码在整个应用中的位置和作用。
当人们谈论上下文感知代码审查时,通常指的是存在于 pull request 本身之外的信息。
不同工具对它的具体定义不尽相同,但通常可以归入以下几类。
这大概是最常见的一种上下文。
工具不再只查看被修改的文件,还会检查周边代码。
例如,当你修改一个 service method 时,它可能会检查:
现有实现
代码仓库其他位置的相似模式
只基于 diff 的审查通常不会这样做。
上下文感知审查会尝试理解这项变更位于系统中的什么位置。
有时,最重要的信息并不在代码里。
而在过去做出的决策里。
每个团队都会随着时间推移逐渐形成自己的约定。有些模式之所以成为标准,是因为实践证明它们行之有效;另一些模式的存在,则可能是因为三年前有人在一次生产事故中吃过亏。
历史上下文可能包括:
以前的 pull request
已被团队接受的实现模式
经验丰富的工程师在审查代码时,会自然而然地利用这些信息。
真正具备上下文感知能力的工具,也应该能够利用其中一部分信息。
现代系统之间的连接方式并不总是显而易见。
一个服务中的微小变更,可能会影响共享库、下游系统、API 或外部集成。
对于拥有多个代码仓库和分布式架构的组织来说,这一点更加重要。
一个 pull request 在自己的代码仓库中看起来可能完全正常,却仍然会在其他地方引发问题。
这就是依赖感知能力如此重要的原因。
这大概是最难解决的问题。
大多数成熟系统都有一些架构规则,但这些规则并不会明确写在每个文件里。
也许服务不应该直接访问某些 domain。
也许特定工作流必须发布事件。
也许某些操作执行之前必须先完成安全检查。
真正理解系统架构的审查工具,应该能够识别一项变更是否违反了这些约定。
这要比检查语法或发现某种常见 bug 模式困难得多。
每当评估一款新的审查工具时,我都会问这个问题。
我不再关注营销宣传,而是把注意力放在它实际生成的反馈上。
我注意到的一点是,优秀的审查评论通常会解释某件事为什么重要。
考虑更新这个实现。
从技术上讲,这确实是一条反馈,但它并没有多大用处。
类似的更新流程会在状态发生变化后发布一个事件。这个实现似乎没有这样做,可能会导致下游行为不一致。
第二条评论表现出了对被修改代码之外其他模式的认知。
这是一个强得多的信号,说明工具确实理解上下文。
我还会观察工具能否将当前变更与那些并未被修改的代码联系起来。
很多工具只分析发生变更的文件。
这本身没有任何问题。
但如果一款工具声称自己能够理解上下文,那么当代码库中的相关部分与当前变更有关时,我希望它能够引用这些内容。
我也会留意它的反馈是否体现了团队约定。
每个工程团队都会围绕日志、测试、安全、错误处理和可观测性形成自己的标准。
最好的审查反馈会让人感到它是针对这个项目量身定制的。
最糟糕的反馈则像是从编程教材里复制过来的泛泛建议。
我们编写代码的方式正在发生变化。
如今,许多团队每天都会使用 Cursor、GitHub Copilot、Claude Code,以及其他 AI 编程助手。
这意味着代码生成速度达到了前所未有的水平。
审查工作量也因此持续增加。
审查者现在做的已经不只是检查代码质量。
他们越来越需要负责判断生成的代码如何融入现有系统、既有模式和架构决策。
这正是上下文能够发挥价值的地方。
并不是因为 AI 会取代人类审查者。
而是因为现代代码库正变得越来越庞大、越来越相互关联,仅凭一个 pull request,已经很难对整个变更进行充分推理。
我觉得 Qodo 的方法有一点很有意思:它会在生成反馈之前,先专注于收集上下文。
它并不只查看发生变更的代码行,还会尝试理解相关文件、代码仓库结构、依赖关系、以往的审查活动以及现有代码模式。
它的目标不是生成更多评论。
而是生成与当前变更真正相关的评论。
任何工具能否做到这一点,最终都应该交给在真实项目中使用它的开发者来判断。
但就我个人而言,与其询问一款审查工具是否使用了 AI,或者它能生成多少条评论,不如用这种方式来评估它。
在这里查看 Qodo:https://www.qodo.ai
“上下文感知代码审查”已经成为一种人人都在使用、却很少有人真正定义的说法。
有些工具主要还是 diff 审查工具。
另一些工具则会尝试先理解代码仓库结构、依赖关系、历史决策和架构模式,然后再生成反馈。
这两种方式并不能简单地说哪一种一定更好。
真正重要的是,你需要弄清楚一款工具实际使用了哪些上下文,以及它的反馈来源于哪里。
因为根据我的经验,最严重的生产问题很少隐藏在语法中。
它们通常隐藏在变更周围的上下文里。
而当你只查看 diff 时,这恰恰是最容易遗漏的部分。
感谢你阅读到这里。如果你觉得这篇文章有用,请点赞并分享。其他人或许也能从中受益。💖
你可以在 X、GitHub、LinkedIn 上与我联系。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。