How to Do Code Reviews Like a Human (Part One)
Michael Lynch argues that most code review writing obsesses over finding bugs and ignores the social half of the process, turning reviews into judgments of the author rather than the code. Drawing on his own review experience, he offers concrete practices: push whitespace, build, test, and lint checks into CI and formatters so humans review logic; settle style disputes with a style guide instead of arguing mid-review; start reviews immediately and keep each round under one business day; stay under roughly 20-50 notes per round and lead with high-level design feedback; include runnable code examples but cap them at two or three per round; never write "you" in a comment, preferring "we", subject-less shorthand, or questions; phrase feedback as requests rather than commands; and tie every note to a stated principle with links to the team style guide or library docs. Aimed at engineers who want reviews that improve code without damaging the team.
Lately, I’ve been reading articles about best practices for code reviews. I notice that these articles focus on finding bugs to the exclusion of almost every other component of a review. Communicating issues you discover in a constructive and professional way? Irrelevant! Just identify all the bugs, and the rest will take care of itself.
最近,我一直在读关于代码审查最佳实践的文章。我注意到,这些文章几乎只关注找 bug,而忽略了审查的其他几乎所有环节。以建设性、专业的方式沟通你发现的问题?不重要!只要找出所有 bug,剩下的自然就搞定了。
So I had a revelation: if this works for code, why not romance? With that, I’m announcing my new ebook to help developers with their love lives:
于是我有了一项重大发现:如果这套方法对代码有效,为什么不能用在恋爱上?因此,我隆重推出我的新电子书,帮助开发者解决感情生活:


My revolutionary ebook teaches you proven techniques for maximizing the number of deficiencies you find in your partner. The ebook does not cover:
Communicating issues to your partner with empathy and understanding.
Helping your partner address their weaknesses.
Based on my reading of code review literature, those parts of a relationship are obvious and not worth discussing.
Does this sound like a good ebook to you? I’m assuming you just yipped “Nonononono!”
我这本革命性的电子书会教你一些经过验证的技巧,让你最大化地找出伴侣身上的缺点。电子书不涉及以下内容:
带着同理心和理解去和伴侣沟通问题。
帮助伴侣改进他们的弱点。
根据我读过的代码审查文献,恋爱关系中的这些部分显而易见,不值一谈。
这听起来像是一本好电子书吗?我猜你刚刚尖叫着说“不不不不不!”
So, why is that the way we talk about code reviews?
I can only assume the articles I’ve read are from the future, where all developers are robots. In that world, your teammates welcome thoughtlessly-worded critiques of their code because processing such information warms their cold, robot hearts.
I’m going to make the bold assumption that you want to improve code reviews in the present, where your teammates are humans. I’ll make the even bolder assumption that a positive relationship with your colleagues is an end in itself and not simply a variable you adjust to minimize your cost-per-defect. How would your review practices change under these circumstances?
In this article, I discuss techniques that treat the code review as not only a technical process but a social one as well.
那么,为什么我们谈论代码审查的方式是这样的呢?
我只能假设,我读到的那些文章来自未来,那时所有开发者都是机器人。在那个世界里,你的队友会欣然接受对他们代码的粗率批评,因为处理这类信息能温暖他们冰冷的机械心。
我大胆假设,你想在当下改善代码审查,而你的队友是人。我再大胆假设,与同事保持良好的关系本身就是目的,而不只是你用来最小化单位缺陷成本的调节变量。在这种情况下,你的审查实践会如何改变?
在本文中,我讨论的技巧不仅把代码审查视为技术过程,也视为社交过程。
The term “code review” can refer to a range of activities, from simply reading some code over your teammate’s shoulder to a 20-person meeting where you dissect code line by line. I use the term to refer to a process that’s formal and written, but not so heavyweight as a series of in-person code inspection meetings.
“代码审查”一词可以指代一系列活动,从站在队友身后随便看看代码,到 20 人开会逐行剖析代码。我使用这个词时,指的是一个正式且书面的流程,但不像一系列现场代码检查会议那么繁重。


The participants in a code review are the author, who writes the code and sends it for review, and the reviewer, who reads the code and decides when it’s ready to be merged in to the team’s codebase. A review can have multiple reviewers, but I assume for simplicity that you are the sole reviewer.
Before the code review begins, the author must create a changelist. This is a set of changes to source code that the author wants to merge in to the team’s codebase.
A review begins when the author sends their changelist to the reviewer. Code reviews happen in rounds. Each round is one complete round-trip between the author and reviewer: the author sends changes, and the reviewer responds with written feedback on those changes. Every code review has one or more rounds.
The review ends when the reviewer approves the changes. This is commonly referred to as giving LGTM, shorthand for “looks good to me.”
代码审查的参与者包括作者和审查者。作者编写代码并提交审查,审查者阅读代码并决定何时可以合并到团队的代码库中。一次审查可以有多个审查者,但为简单起见,我假设你是唯一的审查者。
在代码审查开始之前,作者必须创建一个变更列表。这是作者希望合并到团队代码库中的一组源代码变更。
当作者将变更列表发送给审查者时,审查就开始了。代码审查按轮次进行。每一轮是作者和审查者之间的一次完整往返:作者发送变更,审查者针对这些变更给出书面反馈。每次代码审查都有一个或多个轮次。
当审查者批准变更时,审查结束。这通常被称为给出 LGTM,是“looks good to me”的缩写。
If a programmer sends you a changelist that they think is awesome, and you write them an extensive list of reasons why it’s not, that’s a sensitive message to get across.
That’s one reason I don’t miss IT, because programmers are very unlikable people… In aviation, for example, people who greatly overestimate their level of skill are all dead.
-Philip Greenspun, co-founder of ArsDigita, excerpted from Founders at Work
It’s easy for an author to interpret criticism of their code as an implication that they are an incompetent programmer. Code reviews are an opportunity to share knowledge and make informed engineering decisions. But that can’t happen if the author perceives the discussion as a personal attack.
As if this wasn’t difficult enough, you also have the challenge of conveying your thoughts in writing, where the risk of miscommunication is higher. The author can’t hear your tone of voice or see your body language, so it’s even more important to articulate your feedback carefully. To an author who’s feeling defensive, an innocuous note like, “You forgot to close the file handle,” can read as, “I can’t believe you forgot to close the file handle! You’re such an idiot.”
如果一个程序员发给你一个自认为很棒的变更列表,而你写了一大堆理由说明它为什么不好,这本身就是一条敏感信息。
这也是我不怀念 IT 行业的原因之一,因为程序员是非常不讨人喜欢的群体……比如在航空业,那些严重高估自己技能水平的人全都死了。
——Philip Greenspun,ArsDigita 联合创始人,摘自《Founders at Work》
作者很容易把对其代码的批评理解为暗示自己是个不称职的程序员。代码审查是分享知识和做出明智工程决策的机会。但如果作者认为讨论是针对个人的攻击,这一切就无法实现。
这还不算难,你还要面对书面表达的挑战,其中误解的风险更高。作者听不到你的语气,也看不到你的肢体语言,所以谨慎地表达反馈就更为重要。对于一个感到防备的作者,一句无伤大雅的备注,如“你忘了关闭文件句柄”,可能会被理解为“我真不敢相信你忘了关闭文件句柄!你真是个白痴。”
Techniques 🔗︎
Let computers do the boring parts
Settle style arguments with a style guide
Start reviewing immediately
Start high level and work your way down
Be generous with code examples
Never say “you”
Frame feedback as requests, not commands
Tie notes to principles, not opinions
技巧 🔗︎
让电脑做无聊的部分
用风格指南解决风格争论
立即开始审查
从高层到底层逐步审查
大方地给出代码示例
永远不要说“你”
把反馈写成请求,而非命令
将评论与原则挂钩,而非个人观点
Between interruptions like meetings and emails, the time you have available to focus on code is scarce. Your mental stamina is in even shorter supply. Reading a teammate’s code is cognitively taxing and requires a high level of concentration. Don’t squander these resources on tasks a computer can do, especially when a computer can do them better.
Whitespace errors are an obvious example. Compare how much effort it takes for a human reviewer to find an indenting mistake and work with the author to correct it as opposed to just using an automated formatting tool:
| Effort required with a human reviewer | Effort required with a formatting tool |
|---|---|
| Reviewer searches for whitespace issues and finds incorrect indentation. | |
| Reviewer writes a note calling out the incorrect indentation. | |
| Reviewer rereads their note to make sure that it's worded in a clear, non-accusatory way. | |
| Author reads the note. | |
| Author corrects the code indentation. | |
| Reviewer verifies that the author addressed their note properly. | Nothing! |
The right side is empty because the author uses a code editor that automatically formats the whitespace every time they hit “Save.” At worst, the author sends their code out for review, and the continuous integration solution reports that the whitespace is incorrect. The author fixes the issue without the reviewer ever having to care.
Look for mechanical tasks in your code reviews that you can automate away. Here are the common ones:
| Task | Automated solution |
|---|---|
| Verify the code builds | Continuous integration solution, such as Travis or CircleCI. |
| Verify automated tests pass | Continuous integration solution, such as Travis or CircleCI. |
| Verify code whitespace matches team style | Code formatter, such as ClangFormat (C/C++ formatter) or gofmt (Go formatter). |
| Identify unused imports or unused variables | Code linters, such as pyflakes (Python linter) or JSLint (JavaScript linter). |
Automation helps you make more meaningful contributions as a reviewer. When you can ignore a whole class of issues, such as the ordering of imports or naming conventions for source filenames, it allows you to focus on more interesting things like functional errors or weaknesses in readability.
Automation benefits the author as well. It allows them to discover careless mistakes in seconds instead of hours. The instant feedback makes it easier to learn from and cheaper to fix because the author still has the relevant context in their head. Plus, if they have to hear about a dumb mistake they made, it’s much easier on their ego if they hear it from a computer instead of from you.
Work with your team to build these automated checks directly into the code review workflow (e.g., pre-commit hooks in Git or webhooks in GitHub). If the review process requires the author to run these checks manually, you forfeit most of the benefit. The author will invariably forget on occasion which forces you to continue reviewing for the simple issues that automation is meant to handle instead.
在会议、邮件等打断之间,你能专注于代码的时间非常稀缺。你的脑力更是供不应求。阅读队友的代码非常耗费认知资源,需要高度集中注意力。不要把精力浪费在电脑能做的任务上,尤其是电脑能做得更好的时候。
空白字符错误就是一个明显的例子。对比一下人工审查者发现缩进错误并与作者一起修正它,与直接使用自动格式化工具相比,需要付出多少努力:
| 人工审查者需要付出的努力 | 使用格式化工具需要付出的努力 |
|---|---|
| 审查者查找空白字符问题,发现缩进不正确。 | |
| 审查者写备注指出缩进错误。 | |
| 审查者重读备注,确保措辞清晰、不带指责。 | |
| 作者阅读备注。 | |
| 作者修正代码缩进。 | |
| 审查者确认作者已妥善处理备注。 | 什么都不用做! |
右侧为空是因为作者使用的代码编辑器在每次点击“保存”时会自动格式化空白字符。最坏的情况下,作者把代码提交审查,持续集成方案报告空白字符不正确。作者修正问题,而审查者根本无需操心。
在代码审查中寻找可以自动化处理的机械性任务。以下是常见的例子:
| 任务 | 自动化解决方案 |
|---|---|
| 验证代码能构建 | 持续集成方案,如 Travis 或 CircleCI。 |
| 验证自动化测试通过 | 持续集成方案,如 Travis 或 CircleCI。 |
| 验证代码空白字符符合团队风格 | 代码格式化工具,如 ClangFormat(C/C++ 格式化)或 gofmt(Go 格式化)。 |
| 识别未使用的导入或未使用的变量 | 代码检查工具,如 pyflakes(Python 检查)或 JSLint(JavaScript 检查)。 |
自动化帮助审查者做出更有价值的贡献。当你能忽略一整类问题,比如导入顺序或源文件命名规范,你就可以专注于更有趣的事情,比如功能性错误或可读性弱点。
自动化对作者也有好处。它让作者能在几秒而不是几小时内发现粗心错误。即时反馈让学习变得更容易,修正成本也更低,因为作者脑海中还保留着相关上下文。而且,如果必须听到自己犯的愚蠢错误,从电脑那里听到比从你那里听到对自尊心的打击要小得多。
与团队合作,把这些自动检查直接构建到代码审查工作流中(例如 Git 中的 pre-commit 钩子或 GitHub 中的 webhooks)。如果审查流程要求作者手动运行这些检查,你就丧失了大部分好处。作者总会有忘记的时候,这迫使你继续审查那些本应由自动化处理的简单问题。
Arguments about style are a waste of time in reviews. Consistent style is certainly important, but a code review is not the time to bicker about where to put the curly braces. The best way to excise style debates from your reviews is by keeping a style guide.
在审查中争论风格是浪费时间。一致的风格固然重要,但代码审查不是争论花括号该放哪里的时机。从审查中剔除风格争论的最佳方式是维护一份风格指南。


A good style guide defines not only superficial elements like naming conventions or whitespace rules but also how to use the features of the given programming language. JavaScript and Perl, for example, are packed with functionality — they offer many ways to implement the same logic. A style guide defines The One True Way of doing things so that you don’t end up with half your team using one set of language features while the other half uses a totally different set of features.
Once you have a style guide, you don’t have to waste review cycles arguing with the author about whose naming conventions are best. Just defer to the style guide and move on. If your style guide doesn’t specify a convention about a particular issue, it’s generally not worth arguing about. If you encounter a style issue your guide doesn’t cover and it’s important enough to discuss, hash it out with your team. Then, record the decision in your style guide so you never have to have that discussion again.
好的风格指南不仅定义命名规范或空白字符规则等表面元素,还定义如何使用特定编程语言的功能。例如,JavaScript 和 Perl 功能丰富——实现同一逻辑有很多种方式。风格指南定义了“唯一正确的方式”,这样就不会出现一半团队成员使用一组语言特性,另一半使用完全不同的一组特性。
有了风格指南后,你就不必浪费审查周期与作者争论谁的命名规范更好。只需遵循风格指南,继续审查即可。如果你的风格指南没有对某个特定问题做出规定,通常不值得争论。如果你遇到指南未覆盖且重要到需要讨论的风格问题,和团队一起解决。然后,把决定记录在风格指南中,这样你就再也不用讨论它了。
Option 1: Adopt an existing style guide
If you search online, you can find published style guides ripe for the taking. Google’s style guides are the most well-known, but you can find others if this style doesn’t suit you. By adopting an existing guide, you inherit the benefits of a style guide without the substantial costs of creating one from scratch.
The downside is that organizations optimize their style guides for their own particular needs. For example, Google’s style guides are conservative about using new language features because they have an enormous codebase with code that has to run on everything from a home router to the latest iPhone. If you’re a four-person startup with a single product, you may choose to be more aggressive in using cutting-edge language features or extensions.
Option 2: Create your own style guide incrementally
If you don’t want to adopt an existing guide, you can create your own. Every time a style argument arises during a code review, raise the question to your whole team to decide what the official convention should be. When you reach agreement, codify that decision in your style guide.
I prefer to keep my team’s style guide as Markdown under source control (e.g., GitHub pages). That way, any changes to the style guide go through the normal review process — someone has to explicitly approve the change, and everyone on the team has a chance to raise concerns. Wikis and Google Docs are acceptable options as well.
Option 3: The hybrid approach
By combining options 1 and 2, you can adopt an existing style guide as your base, and then maintain a local style guide to extend or override the base. A good example of this is the Chromium C++ style guide. It uses Google’s C++ style guide as a base, but makes its own changes and additions on top of it.
方式一:采用现有风格指南
如果你在网上搜索,可以找到现成的已发布风格指南,拿来即用。谷歌的风格指南最为知名,但如果这种风格不适合你,也可以找到其他指南。采用现有指南,你就能继承风格指南的好处,而无需承担从零开始创建的巨大成本。
缺点是,各组织会根据自身特定需求优化其风格指南。例如,谷歌的风格指南对使用新语言特性持保守态度,因为他们拥有庞大的代码库,代码需要运行在从家用路由器到最新 iPhone 的各种设备上。如果你是一家只有四个人的初创公司,只做一个产品,你可能会更积极地使用前沿语言特性或扩展。
方式二:逐步创建自己的风格指南
如果你不想采用现有指南,可以创建自己的。每当代码审查中出现风格争论,就把问题提给整个团队,决定官方规范应该是什么。达成一致后,把决定写入风格指南。
我倾向于把团队的风格指南以 Markdown 格式放在源代码控制下(例如 GitHub Pages)。这样,对风格指南的任何修改都要经过正常的审查流程——必须有人明确批准修改,团队每个人都有机会提出顾虑。Wiki 和 Google Docs 也是可以接受的选项。
方式三:混合方式
结合方式一和方式二,你可以采用现有风格指南作为基础,然后维护一份本地风格指南来扩展或覆盖基础指南。一个很好的例子是 Chromium C++ 风格指南。它以谷歌的 C++ 风格指南为基础,但在此基础上做出了自己的修改和补充。
Treat code reviews as a high priority. When you’re actually reading the code and giving feedback, take your time, but start your review immediately — ideally, within minutes.
把代码审查视为高优先级事项。当你真正阅读代码并给出反馈时,可以从容一些,但要立即开始审查——最好在几分钟内开始。


If a teammate sends you a changelist, it likely means that they are blocked on other work until your review is complete. In theory, source control systems allow the author to branch, continue working, and then forward-merge changes from the review into their new branch. In reality, there are about four developers total who can do that efficiently. It takes everyone else so long to untangle three-way diffs that it can cancel out any progress made waiting for the review to come back.
When you start reviews immediately, you create a virtuous cycle. Your review turnaround becomes purely a function of the size and complexity of the author’s changelist. This incentivizes authors to send small, narrowly-scoped changelists. These are easier and more pleasant for you to review, so you review them faster, and the cycle continues.
Imagine that your teammate implements a new feature that requires 1,000 lines of code changes. If they know you can review a 200-line changelist in about 2 hours, they can break their feature into changelists of about 200 lines each and get the whole feature checked in within a day or two. If, however, you take a day to do all code reviews, regardless of size, now it takes a week to get that feature checked in. Your teammate doesn’t want to sit around for a week, so they’re incentivized to send larger code reviews, like 500-600 lines each. These are more costly to review and yield poorer feedback because it’s more difficult to keep context on a 600-line change than a 200-line change.
如果队友发给你一个变更列表,这很可能意味着他们在你完成审查之前被其他工作阻塞。理论上,源代码控制系统允许作者创建分支、继续工作,然后把审查中的变更前向合并到新分支。实际上,总共大约只有四个开发者能高效地做到这一点。其他人要花很长时间才能理清三方差异,这抵消了等待审查返回期间取得的所有进展。
当你立即开始审查时,就创造了一个良性循环。你的审查周转时间完全取决于作者变更列表的大小和复杂度。这会激励作者发送小规模、范围狭窄的变更列表。这些对你来说更容易、更愉快地审查,所以你审查得更快,循环继续。
假设你的队友实现一个新功能,需要修改 1,000 行代码。如果他们知道你能在约 2 小时内审查 200 行的变更列表,他们就可以把功能拆分成每个约 200 行的变更列表,在一两天内把整个功能提交入库。但是,如果你对所有代码审查都花一天时间,不论大小,那么提交那个功能就需要一周。你的队友不想干等一周,所以他们有动力发送更大的代码审查,比如每次 500-600 行。这些审查成本更高,反馈质量更差,因为保持 600 行变更的上下文比 200 行变更要困难得多。
The absolute maximum turnaround on a review round should be one business day. If you’re struggling with a higher-priority issue and can’t complete a round of review in under a day, let your teammate know and give them the opportunity to reassign it to someone else. If you’re forced to decline reviews more than about once per month, it likely means that your team needs to reduce its pace so that you can maintain sane development practices.
一轮审查的绝对最长周转时间应该是一个工作日。如果你正在处理更高优先级的问题,无法在一天内完成一轮审查,就告诉你的队友,让他们有机会把审查转交给其他人。如果你被迫拒绝审查的频率超过每月一次左右,这很可能意味着你的团队需要放慢节奏,以便你能维持健康的开发实践。
The more notes you write in a given review round, the more you risk making the author feel overwhelmed. The exact limit varies by developer, but the danger zone generally begins in the range of 20-50 notes in a single round of review.
If you’re worried about drowning the author in a sea of notes, restrict yourself to high-level feedback in the early rounds. Focus on issues like redesigning a class interface or splitting up complex functions. Wait until those issues are resolved before tackling lower-level issues, such as variable naming or clarity of code comments.
Your low-level notes might become moot once the author integrates your high-level notes. By deferring them to a later round, you save yourself the nontrivial work of writing carefully-worded comments calling out the issues, and you spare the author from processing unnecessary notes. This technique also segments the layers of abstraction you focus on during the review, helping you and the author work through the changelist in a clear, systematic way.
在给定的一轮审查中,你写的备注越多,就越可能让作者感到不知所措。具体限度因开发者而异,但危险区域通常从单轮审查 20-50 条备注开始。
如果你担心用备注淹没作者,就在早期轮次中只提供高层反馈。专注于重新设计类接口或拆分复杂函数等问题。等这些问题解决后,再处理较低层的问题,比如变量命名或代码注释的清晰度。
一旦作者采纳了你的高层备注,你的低层备注可能就变得无关紧要。把它们推迟到后续轮次,你既省去了仔细措辞指出问题的不小工作量,也让作者免于处理不必要的备注。这个技巧还能把你在审查中关注的抽象层次分段,帮助你和作者清晰、系统地处理变更列表。
In an ideal world, the code author would be thankful for every review they receive. It’s an opportunity for them to learn, and it protects them from mistakes. In reality, there are a number of external factors that could cause the author to perceive the review negatively and resent you for giving them notes. Maybe they’re under pressure to meet a deadline, so anything other than your instant, rubber-stamp approval feels like obstruction. Maybe you haven’t worked together much, so they don’t trust that your feedback is well-intentioned.
A great way to make an author feel good about the review process is to find opportunities to give them gifts during the review. And what’s the gift all developers love to receive? Code examples, of course.
If you lighten the author’s load by writing out some of the changes you’re suggesting, you demonstrate that you are generous with your time as a reviewer.
For example, imagine that you have a colleague who is not familiar with the list comprehensions feature of Python. They send you a code review that includes these lines:
urls = []
for path in paths:
url = 'https://'
url += domain
url += path
urls.append(url)
Responding, “Can we simplify this with a list comprehension?” will annoy them because now they have to spend 20 minutes researching something they’ve never used before.
They will be much happier to receive a note like the following:
Consider simplifying with a list comprehension like this:
urls = ['https://' + domain + path for path in paths]
This technique is not limited to one-liners. I’ll often create my own branch of the code to demonstrate a large proof of concept to the author, such as breaking up a large function or adding a unit test to cover an additional edge case.
Reserve this technique for clear, uncontroversial improvements. In the list comprehension example above, few developers would object to an 83% reduction in lines of code. In contrast, if you write a lengthy example to demonstrate a change that is “better” based on your own personal taste (e.g., style changes), code examples make you look pushy instead of generous.
Limit yourself to two or three code examples per review round. If you start writing the author’s whole changelist for them, it signals that you don’t think they’re capable of writing their own code.
在理想世界里,代码作者会感谢收到的每一次审查。这是他们学习的机会,也能保护他们免于犯错。现实中,很多外部因素可能导致作者对审查产生负面看法,并因为你的备注而怨恨你。也许他们正承受着截止日期的压力,所以任何不是即时盖章批准的事情都像是阻碍。也许你们合作不多,所以他们不信任你的反馈是善意的。
让作者对审查过程感到满意的一个好方法,是在审查中找机会送他们礼物。所有开发者都喜欢收到什么礼物?当然是代码示例。
如果你把建议的修改写出来,减轻作者的负担,就表明你作为审查者慷慨地付出了时间。
例如,假设你有一位同事不熟悉 Python 的列表推导式。他们发给你一个代码审查,包含以下代码:
urls = []
for path in paths:
url = 'https://'
url += domain
url += path
urls.append(url)
回复“我们能不能用列表推导式简化一下?”会让他们恼火,因为现在他们得花 20 分钟研究从未用过的东西。
他们会更乐意收到这样的备注:
考虑用列表推导式简化成这样:
urls = ['https://' + domain + path for path in paths]
这个技巧不仅限于单行代码。我经常创建自己的代码分支,向作者演示大型概念验证,比如拆分大函数或添加单元测试覆盖额外的边缘情况。
把这个技巧留给明确、无争议的改进。在上面的列表推导式例子中,很少会有开发者反对将代码行数减少 83%。相反,如果你写一个冗长的示例来演示一个基于个人品味的“更好”的改动(例如风格修改),代码示例就会让你显得咄咄逼人,而不是慷慨。
每轮审查限制在两到三个代码示例。如果你开始替作者写整个变更列表,那就表明你认为他们没有能力写自己的代码。


This one is going to sound weird, but hear me out: never use the word “you” in a code review.
The decisions you reach in a review should be based on what makes the code better rather than who came up with the idea. Your teammate put significant effort into their changelist and is likely proud of the work they did. Their natural reaction to hearing criticism of their work is to feel defensive and protective.
Word your feedback in a way that minimizes the risk of raising your teammate’s defenses. Be clear that you’re critiquing the code, not the coder. When an author sees “you” in a comment, it brings their focus away from the code and back to themselves. This increases the risk that they’ll take your criticism personally.
Consider this harmless comment:
You misspelled ‘successfully.’
The author can interpret that note in two very different ways:
Interpretation 1: Hey, good buddy! You misspelled ‘successfully.’ But I still think you’re smart! It was probably just a typo.
Interpretation 2: You misspelled ‘successfully,’ dumbass.
Contrast this with a note that omits “you”:
sucessfully -> successfully
The latter note is a simple correction and not a judgment of the author.
Fortunately, it’s easy to rewrite your feedback to avoid the word “you.”
Option 1: Replace ‘you’ with ‘we’
Can you rename this variable to something more descriptive, like seconds_remaining?
becomes:
Can we rename this variable to something more descriptive, like seconds_remaining?
“We” reinforces the team’s collective responsibility for the code. The author may move on to a different company and so might you, but the team who owns this code will remain in one form or another. It can sound silly to say “we” when it’s clearly something you expect the author to do themselves, but silly is better than accusatory.
Option 2: Remove the subject from the sentence
Another way to avoid using “you” is to use a shorthand that omits the subject from the sentence:
Suggest renaming to something more descriptive, like seconds_remaining.
You can achieve a similar effect with the passive voice. I generally avoid the passive voice like the plague in my technical writing, but it can be a helpful way of writing around “you”:
This variable should be renamed to something more descriptive, like seconds_remaining.
An additional option is to phrase it as a question, beginning with “what about…” or “how about…”:
What about renaming this variable to something more descriptive, like seconds_remaining?
这一点听起来可能有点怪,但请听我说完:在代码审查中永远不要使用“你”这个词。
你在审查中做出的决定应该基于什么能让代码更好,而不是谁提出了这个想法。你的队友为变更列表付出了大量努力,很可能为自己的工作感到自豪。他们听到对自己工作的批评时,自然反应是防备和保护。
措辞时,要尽量减少激起队友防御心理的风险。明确表示你是在批评代码,而不是写代码的人。当作者在评论中看到“你”时,他们的注意力会从代码转移回自己身上。这增加了他们把批评视为针对个人的风险。
看看这条看似无害的评论:
你拼错了‘successfully’。
作者可以用两种截然不同的方式解读这条备注:
解读一:嘿,好哥们!你拼错了‘successfully’。但我仍然觉得你很聪明!可能只是笔误。
解读二:你拼错了‘successfully’,蠢货。
对比一下省略了“你”的备注:
sucessfully -> successfully
后一条只是简单的纠正,而非对作者的评价。
幸运的是,重写反馈以避免“你”这个词很容易。
方式一:用“我们”代替“你”
你能把这个变量重命名为更具描述性的名字吗,比如 seconds_remaining?
变成:
我们能不能把这个变量重命名为更具描述性的名字,比如 seconds_remaining?
“我们”强化了团队对代码的集体责任。作者可能跳槽到另一家公司,你也可能,但拥有这段代码的团队会以某种形式继续存在。当某件事明显是你期望作者自己去做时,说“我们”可能听起来有点傻,但傻总比指责好。
方式二:从句子中去掉主语
另一种避免使用“你”的方法是使用省略主语的简写:
建议重命名为更具描述性的名字,比如 seconds_remaining。
你也可以用被动语态达到类似效果。我在技术写作中一般像躲瘟疫一样避免被动语态,但它是绕开“你”的一种有用方式:
这个变量应该重命名为更具描述性的名字,比如 seconds_remaining。
另一种选择是把它写成问句,以“那……怎么样”或“不如……”开头:
不如把这个变量重命名为更具描述性的名字,比如 seconds_remaining?


Code reviews require more tact and care than usual communication because there’s a high risk of derailing the discussion into a personal argument. You would expect reviewers to dial up their politeness in reviews, but bizarrely I’ve found them to go the opposite direction. Most people never say to a co-worker, “Hand me that stapler, then fetch me a soda.” But I’ve seen numerous reviewers frame feedback with similarly pushy commands, such as, “Move this class to a separate file.”
Err on the side of being annoyingly gentle in your feedback. Frame your notes as requests or suggestions, not commands.
Compare the same note framed in two different ways:
| Feedback framed as command | Feedback framed as request |
|---|---|
| Move the Foo class to a separate file. | Can we move the Foo class to a separate file? |
People like to feel in control of their own work. Making a request of the author gives them a sense of autonomy.
Requests also make it easier for the author to push back politely. Maybe they have a good reason for their choice. If you frame your feedback as a command, any pushback from the author comes across as disobedience. If you frame your feedback as a request or a question, the author can simply answer you.
Compare how combative the conversation seems depending on how the reviewer frames their initial note:
| Feedback framed as command (Combative) | Feedback framed as request (Cooperative) |
|---|---|
| Reviewer: Move the Foo class to a separate file.<br><br>Author: I don’t want to do that because then it’s far away from the Bar class. Clients will almost always use the two together. | Reviewer: Can we move the Foo class to a separate file?<br><br>Author: We could, but then it’s far away from the Bar class, and clients will generally use these two classes together. What do you think? |
See how much more civil the conversation becomes when you construct imaginary dialog to prove your point frame your notes as requests instead of commands?
代码审查比平常的沟通需要更多的圆融和谨慎,因为讨论很容易偏离成个人争论。你可能会期望审查者在审查中更加礼貌,但奇怪的是,我发现他们往往走向反面。大多数人从不对同事说:“把订书机递给我,再去给我拿瓶汽水。”但我见过很多审查者用同样强硬的命令式措辞给出反馈,比如:“把这个类移到单独的文件里。”
在反馈中宁可过于温和,也不要强硬。把你的备注写成请求或建议,而不是命令。
对比同一条备注的两种措辞:
| 以命令形式给出的反馈 | 以请求形式给出的反馈 |
|---|---|
| 把 Foo 类移到单独的文件里。 | 我们能不能把 Foo 类移到单独的文件里? |
人们喜欢对自己的工作有掌控感。向作者提出请求,会让他们感到自主。
请求也让作者更容易礼貌地反驳。也许他们的选择有充分的理由。如果你把反馈写成命令,作者的任何反驳都会显得像不服从。如果你把反馈写成请求或问题,作者就可以直接回答你。
对比一下,审查者如何措辞初始备注,会让对话显得多么不同:
| 以命令形式给出的反馈(好斗) | 以请求形式给出的反馈(合作) |
|---|---|
| 审查者:把 Foo 类移到单独的文件里。<br><br>作者:我不想那样做,因为那样它离 Bar 类太远了。客户端几乎总是同时使用这两个类。 | 审查者:我们能不能把 Foo 类移到单独的文件里?<br><br>作者:可以,但那样它离 Bar 类就远了,而客户端通常会同时使用这两个类。你觉得呢? |
看,当你把备注写成请求而不是命令时,对话变得文明多了——你还可以编造对话来证明自己的观点。
When you give the author a note, explain both your suggested change and the reason for the change. Instead of saying, “We should split this class into two,” it’s better to say, “Right now, this class is responsible for both downloading the file and parsing it. We should split it up into a downloader class and parsing class per the single responsibility principle.”
Grounding your notes in principles frames the discussion in a constructive way. When you cite a specific reason, like, “We should make this function private to minimize the class’ public interface,” the author can’t simply respond, “No, I prefer it my way.” Or rather, they can, but it would look silly because you demonstrated how the change satisfies a goal, and they just stated a preference.
Software development is both an art and science. You can’t always articulate exactly what is wrong with a piece of code in terms of established principles. Sometimes code is just ugly or unintuitive, and it’s hard to pin down why. In these cases, explain what you can, but keep it objective. If you say, “I found this hard to understand,” that’s at least an objective statement, as opposed to, “this is confusing,” which is a value judgment and may not be true for every person.
Provide supporting evidence where possible in the form of links. The relevant section of your team’s style guide is the best link you can provide. You can also link to documentation for the language or library. Highly-upvoted StackOverflow answers can work as well, but the farther you stray from authoritative documentation, the shakier your evidence becomes.
当你给作者写备注时,既要说明建议的修改,也要说明修改的原因。与其说“我们应该把这个类拆成两个”,不如说“目前这个类同时负责下载文件和解析文件。根据单一职责原则,我们应该把它拆分成下载器类和解析类。”
把备注建立在原则上,能让讨论以建设性的方式展开。当你引用具体理由,比如“我们应该把这个函数设为私有,以最小化类的公共接口”,作者就不能简单地回答“不,我更喜欢我的方式。”或者说,他们可以,但会显得很傻,因为你已经证明了改动如何满足一个目标,而他们只是陈述了偏好。
软件开发既是艺术也是科学。你并不总能根据既定原则准确说出代码哪里有问题。有时代码就是丑陋或不直观,很难说清原因。在这些情况下,你能解释多少就解释多少,但要保持客观。如果你说“我觉得这个很难理解”,至少是一个客观陈述,而“这很令人困惑”则是价值判断,可能对每个人都不成立。
尽可能以链接形式提供支持证据。团队风格指南的相关章节是最好的链接。你也可以链接到语言或库的文档。高赞的 StackOverflow 答案也可以,但离权威文档越远,你的证据就越站不住脚。
If you enjoyed this post, check out the second half of this article, which focuses on bringing reviews to a successful close without ugly conflict. It includes techniques for:
Handling excessively large code reviews,
Recognizing opportunities to give praise,
Respecting the scope of a review, and
Mitigating stalemates.
How to Do Code Reviews Like a Human (Part two) 🔗︎
如果你喜欢这篇文章,请查看它的下半部分,重点是如何在没有丑陋冲突的情况下成功结束审查。它包括以下技巧:
处理过大的代码审查,
识别表扬的机会,
尊重审查的范围,以及
缓解僵局。
如何像人一样做代码审查(第二部分)🔗︎
Edited by Samantha Mason. Illustrations by Loraine Yow. Thanks to @global4g for providing valuable feedback on an early draft of this post.
编辑:Samantha Mason。插图:Loraine Yow。感谢 @global4g 对本文早期草稿提供了宝贵反馈。