On compassionate code review

Programmers, think about the number of times you've had your code reviewed by others.

What percentage of those times did you feel a sense of trepidation beforehand? How many of those times did you feel discouraged, embarrassed, or demoralized afterward?

Now think about the times when you've had a code reviewer who made you feel genuinely valued, recognized the good things you did, offered suggestions for improvement that felt encouraging rather than belittling, and approached their job as collaborative rather than oppositional.

I'd venture to guess that most people have experienced more of the former than the latter.

That's unfortunate for many reasons, but I'll highlight two, one pretty obvious and one slightly less so.

The more obvious reason is that uncompassionate code reviews affect morale. Nobody enjoys being dumped on.

But another reason why uncompassionate code reviews can be so damaging is that they aren't as effective at improving overall code quality.

Again, think back to a time when you were fortunate to have a compassionate, encouraging code reviewer. Did that mean they were wishy-washy, less engaged, less invested in code quality? I'd wager they weren't.

Typically, the people who practice compassionate code reviews are just as invested in code quality as people who take a less encouraging approach. But they're more invested in the author's growth and success.

So not only do compassionate code reviewers help eliminate the stress and discouragement that so often accompany the code-review process, but also, they tend to be proactive rather than reactive at addressing deficiencies. If they want code authors to be successful and find no joy in calling out errors, then they are motivated to look for ways to surface those errors earlier, attach stronger guard rails to existing processes, and share knowledge about good software engineering practices outside of code reviews.

Compassionate code review ultimately rests on putting yourself in the author's place. If they've done well, you should want them to feel proud of their work. Even the smallest amount of positive feedback can feel much more uplifting to the author than an approval without comment. On the other hand, if they've bungled it up, you should want them to emerge having learned from the experience, not feeling burned from the experience.

How to practice compassionate code review

Below are a few suggestions about how to become a more compassionate code reviewer. Some of the specific suggestsions are most applicable for projects where there is an ongoing working relationship between authors and reviewers, but even if your project accepts one-off contributions from the public, you can still find general principles that apply.

If you have any other tips to add, I'd love to hear from you!

Establish expectations beforehand. Code authors will be best prepared for your review process if you have talked with them beforehand about how you review code, what you're looking for, how you give feedback, and what they can expect that feedback to look like. It's also helpful to touch on what they should do if they feel you've missed the mark in your feedback.

Bookend criticism with praise. Even when it's clear that criticism is warranted, you can influence how that criticism is received by the author by also complimenting them on the things they did well. One tried-and-true formula is to begin and end your review on a positive note. This helps the author put your feedback into perspective and recognize that you are considering both the good and the bad, not trying to tear them down.

Personalize your praise. You may have heard the adage, "Praise in public, criticize in private." While it certainly springs from a compassionate mindset, the truth is many people find compliments during one-on-one conversations more valuable and authentic than recognition given in team or company meetings, which can come off as perfunctory. The most effective praise is typically a mix of both, and it's personalized to the individual. Try to learn what types of praise the code author values most, and tailor your compliments accordingly.

Deliver criticism on a need-to-know basis. Another way the adage "Praise in public, criticize in private" falls short is that while delivering criticism privately is often the right call, sometimes it's not so simple. For instance, if another reviewer makes an offensive comment toward a code reviewer or other participant in your project, making the choice to criticize that person in private is the wrong call, because it leaves the rest of the team in the dark about whether you're tolerating the abusive behavior or addressing it. Rather than adopting "Critize in private" as your manta, resolve to deliver criticism on a need-to-know basis. If, during a code review, you notice a problem that can be easily resolved without calling attention to it, consider addressing it privately, rather than posting it for others to see. Or, if it's an error that you've seen other team members make and you want to address it more broadly, look for an opportunity to do so that does not specifically call out the one instance that's top of mind. However, when you need to immediately address abusive conduct in a public way, don't shy away from doing it in the sunlight — but be sure to also follow up privately with those involved to make sure expectations are clear.

Avoid "Request Changes." GitHub allows code reviewers to complete their review using one of three statuses: "Approve," which signals that the pull request can be merged; "Comment," which is more neutral and does not signal approval, or "Request changes," which explicitly signals that the pull request should not be merged until the feedback is addressed. In general "Request changes" should be used very sparingly, and only in situations where there is a real need. For instance, it's possible to block the ability to merge a PR until it's received a certain number of approvals, which makes "Request changes" less of a necessary indicator.

Label non-blocking feedback. Sometimes you might wish to offer some general feedback about the code you're reviewing, but there's no reason it has to hold up merging the code. One convention that I've found helpful is prefixing such feedback with an agreed-upon term, such as "NAB" (not a blocker) or "Bikeshedding" or "Nitpick." Code authors can feel free to treat these comments as suggestions rather than imperatives, or agree to address them in a subsequent unit of work, without having to block merging the code they've submitted. This convention helps code authors better understand the expectations you have for any piece of feedback.

Try to understand why. One of the most important ways you can help code authors improve is by understanding what led them to make an observed error, or what led them to make a less-than-optimal design decision. Did they lack context? How can you make that context more easily discoverable? Did they fail to anticipate edge cases? Can test coverage be improved to make those edge cases more clear? Did they misunderstand the requirements? How can the process of communicating those requirements be refined to make them less ambiguous? Is there a tool or technique they were unaware of that could have been helpful? How can you surface it in a way that benefits not only the current code under review, but future contributors to the project?

Assume competence. If you find that the author has taken an unusual approach to a particular problem, rather than assuming that they are simply incompetent or ignorant of the way you would have approached it, assume that they are competent and perhaps know something you don't know that led them to adopt their approach. You might begin the conversation by saying something like, "I noticed you used method _____ to accomplish this. I normally see it done via method ______, which has the benefit of _______. Would it be appropriate to try that here?" This gives the code author the ability to say, "Oh, I wasn't aware of that method. Yes, I'll use that instead." But it also gives the code author the ability to say, "I considered that method, but here are the reasons why I decided to implement it differently." (Note: Even if there is a defensible reason for why the author has taken an unusual approach, it's often worth encouraging the author to document, via inline comments or other means, departures from ordinary practices or methods, so future maintainers understand the rationale.)

Be prepared for pushback. It's possible that the feedback you give, however tactfully presented, might not be well received. This can happen even if there's no dispute about the facts, but the author doesn't take criticism well or approaches any code review as a power struggle. The best way to proactively address this type of reaction is to establish a healthy working relationship with them ahead of time. But in the moment, remember that taking the high road and not engaging in petty squabbles — however satisfying it might feel — is the compassionate approach. Since you are committed to treating code reviews as a collaboration, any "victory" that's accomplished by taking the author down a peg is likely to damage your ability to collaborate effectively.

Look for takeaways. If you start to observe patterns or categories of missteps in the code you review, ask yourself what actions you or your group might take to address them in a way that makes them less likely to appear in future submissions. Do test suites or automated checks need to be strengthened? Does documentation need to be improved? Would it be useful to do a tech talk or organize some other professional-development session to help contributors level up? Don't limit your scope to just the code itself; you might also try to discern takeaways about the code-review process. Are authors expressing frustration about the difficulty of getting their code reviewed and approved? What changes to existing processes might help? Ultimately, your task as a compassionate code reviewer is to show code authors that they are valued and you are committed to making the review process as painless as possible.

About Shaun

Shaun Gallagher is the author of three popular science books and one silly statistics book:

He's also a software engineering manager and lives in northern Delaware with his wife and children.

Visit his portfolio site for more about his books and his programming projects.

The views expressed on this blog are his own and do not necessarily represent the views of his publishers or employer.

Recent posts

This online experiment identifies dogmatic thinking

Adapted from a 2020 study, this web experiment tests a cognitive quirk that contributes to dogmatic worldviews.

Read more

Distributism: A Kids' Guide to a Third-Way Economic System

This student guide explores three economic systems (capitalism, socialism, and distributism) and explains how distributism is different from the other two.

Read more

You can thrive in a high-paying career without being money-driven

What if making money is not one of your top goals? And what if you happen to stumble into a high-paying career nonetheless?

Read more

On compassionate code review

How to build up and encourage code authors during the review process

Read more

Rules for Poems

A poem about all the rules you can break — and the one rule you can't.

Read more

Other recent blog posts