Reviewing code is a skill
Reviewing code is a skill
代码审查是一项技能
Intended audience: Software developers interested in getting better at developing software. Initially, I meant this post more for junior developers, but some parts are more applicable for tech leads etc. So if the post appears a bit muddled, please accept this apology from my inner Pascal, “Sorry, I did not have the time to break it up into two posts.” 目标读者: 有意提升软件开发能力的软件开发者。起初,我打算将这篇文章主要写给初级开发者,但其中一些部分也适用于技术主管等角色。因此,如果文章看起来有些杂乱,请接受我内心深处帕斯卡(Pascal)的道歉:“抱歉,我没时间把它拆成两篇文章来写。”
In developer communities, there has been a lot of discussion on code review, especially over the course of 2025-2026. For example, you may have seen claims like: Not necessarily all from the same people. “Code review is the bottleneck” “Mandatory pre-merge code review is for low-trust environments; you should push directly to main” “Code review doesn’t find bugs” “Code review is not for X, it’s for Y” “LLMs are better than humans at reviewing code” “LLM code reviews are much better than humans at finding edge cases/bugs” “You should stop looking at the code; you should be doing XYZ instead” and so on. 在开发者社区中,关于代码审查的讨论非常多,尤其是在 2025-2026 年期间。例如,你可能见过诸如此类的观点(未必出自同一人之口):“代码审查是瓶颈”、“强制性的合并前代码审查只适用于低信任环境;你应该直接推送到主分支”、“代码审查发现不了 Bug”、“代码审查不是为了做 X,而是为了做 Y”、“大模型(LLM)在代码审查方面比人类更强”、“大模型代码审查在发现边缘情况/Bug 方面远胜人类”、“你不应该盯着代码看,而应该去做 XYZ”等等。
Out of this, zooming in on “Code review is not for X, it’s for Y” for a moment, the research has the following to say: By coding our interview data, we identified four key themes for what Google developers expect from code reviews: education, maintaining norms, gatekeeping, and accident prevention. Education regards either teaching or learning from a code review and is in line with the initial reasons for introducing code review; norms refer to an organization preference for a discretionary choice (e.g., formatting or API usage patterns); gatekeeping concerns the establishment and maintenance of boundaries around source code, design choices or another artifact; and accidents refer to the introduction of bugs, defects or other quality related issues. – Modern Code Review: A Case Study at Google (2018) 在此,我们暂时聚焦于“代码审查不是为了做 X,而是为了做 Y”这一观点,相关研究指出:通过对访谈数据进行编码,我们确定了 Google 开发者对代码审查的四个核心期望:教育、维护规范、把关(Gatekeeping)以及事故预防。教育是指通过代码审查进行教学或学习,这与引入代码审查的初衷一致;规范是指组织对某些非强制性选择的偏好(例如格式或 API 使用模式);把关涉及围绕源代码、设计选择或其他产物建立和维护边界;事故则指引入 Bug、缺陷或其他质量相关问题。——《现代代码审查:Google 案例研究》(2018)
Similarly, Expectations, outcomes, and challenges of modern code review (2013) points out: Our study reveals that while finding defects remains the main motivation for review, reviews are less about defects than expected and instead provide additional benefits such as knowledge transfer, increased team awareness, and creation of alternative solutions to problems. Moreover, we find that code and change understanding is the key aspect of code reviewing and that developers employ a wide range of mechanisms to meet their understanding needs, most of which are not met by current tools. 同样,《现代代码审查的期望、成果与挑战》(2013)指出:我们的研究表明,虽然发现缺陷仍然是审查的主要动机,但审查在发现缺陷方面的作用不如预期,反而提供了诸如知识传递、提高团队意识以及创造问题替代方案等额外益处。此外,我们发现代码和变更的理解是代码审查的关键方面,开发者采用了多种机制来满足他们的理解需求,而其中大多数需求目前的工具都无法满足。
So at least, hopefully we can agree that code review serves many purposes. I will get to the other points in a bit. But before that, I want to articulate a framing which I haven’t seen much elsewhere. Namely, that reviewing code is a skill. Specifically, I posit that: It’s possible to get better at reviewing code. By “better”, I mean across all of the purposes above: catching bugs, catching design issues, increasing one’s awareness of what’s going on, and understanding the code. It’s possible to teach someone to get better at reviewing code. By virtue of it being a fairly modern skill, we don’t quite know where the human skill ceiling lies (e.g. what is the Pareto frontier in terms of speed vs quality?). If you’re a software developer, and if you believe that people will continue to be involved in the development and maintenance of programs for the foreseeable future, then it’s valuable to get better at reviewing code. 至少,希望我们能达成共识:代码审查具有多种用途。我稍后会讨论其他观点。但在那之前,我想阐述一个我在其他地方很少见到的框架,即:代码审查是一项技能。具体来说,我认为:代码审查是可以提升的。我所说的“提升”涵盖了上述所有目的:发现 Bug、发现设计问题、提高对项目进展的感知,以及理解代码。教导他人提升代码审查能力是可能的。由于这是一项相当现代的技能,我们尚不清楚人类的技能上限在哪里(例如,在速度与质量之间的帕累托最优边界在哪里?)。如果你是一名软件开发者,并且相信在可预见的未来人类仍将参与程序的开发和维护,那么提升代码审查能力是非常有价值的。
First, I will give three small examples taken from the past few weeks of work of me finding bugs when reviewing code. I’ve specifically chosen bugs for discussion because they’re relatively unambiguous. Next, I will provide some of my own historical background related to code review, and some arguments in favor of the core thesis. After that, I discuss some ideas for experimenting with and improving code review. Finally, I discuss the aforementioned oft-repeated memes around code review and how they hold up to scrutiny with the thesis in mind. Let’s get started. 首先,我将举三个小例子,这些都是我过去几周在代码审查中发现的 Bug。我特意选择这些 Bug 进行讨论,因为它们相对明确。接下来,我将介绍我个人与代码审查相关的背景,并提出一些支持核心论点的论据。之后,我将讨论一些关于实验和改进代码审查的想法。最后,我将讨论上述关于代码审查的陈词滥调,并结合本文的核心论点审视它们是否经得起推敲。让我们开始吧。
A tale of three almost-introduced bugs. A bunch of details have been elided in the course of explaining the different examples below, in an attempt to make them digestible. It may be valuable to keep an eye on stray thoughts of the form, “well, that seems like a code smell, no wonder you almost had that bug” or “duh, this could’ve been avoided with XYZ”. In two out of the three cases, the person who wrote the PR had experience with the surrounding code. The other thing to note is that LLM reviews with a mixture of high-end coding models (around Jun 2026) were run for all of the PRs described below. They did not catch the issues that I caught. 三个差点被引入的 Bug 的故事。为了让下文的例子易于理解,我省略了许多细节。如果你脑海中闪过“嗯,这看起来像代码异味(Code Smell),难怪差点引入 Bug”或者“废话,用 XYZ 不就能避免了吗”之类的想法,这很有价值。在三个案例中的两个里,编写 PR 的人对相关代码是有经验的。另外需要注意的是,下文描述的所有 PR 都经过了(2026 年 6 月左右的)高端编码模型组合的 LLM 审查,但它们都没有发现我所发现的问题。
It may be helpful to consult this handy table from Lorin Hochstein’s Traditional versus resilience engineering views: The post is short and recommended reading. The table below is a subset of the one in the original post. 参考 Lorin Hochstein 的《传统观点与韧性工程观点》中的这张便捷表格可能会有所帮助:这篇文章很短,值得一读。下表是原文表格的子集。
| Traditional view focuses on | Resilience engineering view focuses on |
|---|---|
| objectives | navigating complexity |
| production pressure | interaction of multiple factors |
| reducing complexity | human variability as asset |
| root cause | human variability as liability |
| 传统观点关注 | 韧性工程观点关注 |
|---|---|
| 目标 | 驾驭复杂性 |
| 生产压力 | 多因素交互 |
| 降低复杂性 | 将人类变异性视为资产 |
| 根本原因 | 将人类变异性视为负债 |
One way to read the cases below is to try to think about both sides of the table as you read them. 阅读下文案例时,一种方法是尝试同时从表格的两侧去思考。
Writing some git configuration
We use our own devboxes (Disposable VMs used for software development) at $WORK which run on EC2 instances. The logic for starting things has two subprocesses: One background process, to initialize state which isn’t needed right away. This process may or may not have finished by the time the user starts using the devbox. One foreground process, which needs some extra data from the user’s laptop, and blocks the user until it’s done. Only after this process finishes can the user start using the devbox. To reduce latency, we’ve been working on moving more operations to the background process. In this spirit, one of my colleagues created a PR to move some of the modifications to the global ~/.gitconfig.
编写 Git 配置
我们在公司使用自己的 devboxes(用于软件开发的临时虚拟机),它们运行在 EC2 实例上。启动逻辑包含两个子进程:一个后台进程,用于初始化非即时需要的状态。当用户开始使用 devbox 时,该进程可能已经完成,也可能尚未完成。另一个是前台进程,它需要用户笔记本电脑上的额外数据,并会阻塞用户直到完成。只有在该进程完成后,用户才能开始使用 devbox。为了降低延迟,我们一直致力于将更多操作移至后台进程。本着这种精神,我的一位同事创建了一个 PR,将一些修改移至全局的 ~/.gitconfig 中。