Suffering from review fatigue? Here's how to level up your code review process.
Code review is something we do daily in engineering teams, but it doesn't get enough attention. As engineering leaders, how might we optimize processes around code review to reduce stress and maximize growth opportunities for our engineers?
In this article, I’ll talk about two key code review concepts that I’ve applied in my own teams to support and grow my reports. The first approach is about minimizing focus on trivial issues and maximizing focus on issues that lead to learning. The second concept is about culture, and adopting appropriate language and attitudes around code reviews.
Before we dive into these approaches, let’s talk about why code review processes need to change.
Engineering teams are suffering from review fatigue
Are your teams experiencing review fatigue? If so, you’ve probably noticed the following pattern play out in your code reviews:
10 lines of code = “5 issues”
600 lines of code = “Looks fine”
Review fatigue occurs when there are too many potential questions and decisions placed onto the reviewer. This can be attributed to PRs that are too wide in scope, too large in size, or too complex overall. The consequences are longer cycle times, less thorough reviews, and increased risk to the codebase. This leads to missed learning opportunities for both code submitters and reviewers, and engineering teams become weaker overall.
We can’t (and shouldn’t) rely on individual developers to power through nightmare PRs. Instead, we need to institutionally combat review fatigue through our processes.
So, what can we do?
1. Minimize focus on trivial issues and maximize focus on non-trivial issues
I call this approach, “min-max focus”. It’s about putting less effort into unimportant issues, and more into issues that lead to learning. This way, we can reduce review fatigue, and create more growth opportunities for the team.
a) Minimize focus on trivial issues
We want to lower the overall number of trivial decisions a reviewer has to make during a particular code review. This means reducing ambiguity and automating as much as possible. There should not be ambiguity around the coding style of a particular codebase. Each codebase should have a clear style guide that contributors can follow. Use a linter tool to automate identification of trivial style or formatting issues. Make use of pull request templates to facilitate communication and standards of the codebase. A good pull request template will include things like a checklist and divide the description into sections.
b) Maximize focus on non-trivial issues
In addition to limiting unnecessary decision-making, we want to increase focus on the important issues during code review. Pull requests should have a narrow scope. The number of questions a reviewer needs to consider increases exponentially as the scope of a PR increases. Some of the ways engineers can reduce the scope of their PRs actually begins with ticket breakdown. Following the single responsibility principle (SRP), as leaders we want to facilitate the breakdown of tasks into smaller chunks which can address individual concerns. Additionally the submitter can ask for a narrower review, such as a design review or an architecture review.
We should strive for small PR sizes to combat review fatigue. There are many variables to account for but a good rule of thumb is that PRs in excess of 250 lines of code can be considered too large. In general, a single large PR will take longer to review than multiple smaller PRs with the same overall lines of code. The delay to review is also higher, as an engineer has to allocate a larger amount of time and mental effort in their day.
2. Foster a healthy code review culture
Code review should be viewed as an opportunity not only to ship better code in a shared codebase, but to grow as individuals and teams. As leaders, it’s our job to foster the right attitude towards code review on our teams. Here are a few ways we can do this:
a) Promote team ownership
Code review isn’t a competition. We are on the same team, and we should strive to level each other up and write the best possible code. Shared ownership of the code is an important value to reiterate to your teams. Code attachment is a common trap in which engineers will be adverse to feedback and changes to their code, especially for larger PRs. Culturally, we can avoid this trap by having the right attitude on the team and ensuring that the feedback is provided correctly.
b) Use indirect inclusive language
Team members should understand how to give effective code review feedback. This training should be included as part of the onboarding process.
Code review feedback should be polite and respectful. As a general rule, we should lean towards using indirect and inclusive language.
Direct language: “Make this change here.”
Indirect language: Should we make this change here?”
Indirect language is unassuming and creates opportunities for the speaker and listener to provide reasoning. Inclusive language such as using, “should we?” instead of, “you should” fosters team ownership of the code.
c) Provide reasoning
I’ve seen many engineers request a change without understanding the reasoning themselves. In this situation, there is a lack of deep understanding behind the changes, and that lack of conscious knowledge is passed forward.
How can we address this with process or culture? Asking for reasoning and providing reasoning should be the default behavior. It takes effort from both the reviewer and the submitter but it pays off. Discussing the ‘why’ and not just the ‘what’ is a multiplier for growth opportunities and knowledge-sharing.
Reflections
Code review is a fundamental part of our work, and it’s time we level up our processes. I hope this article has provided some tools and learnings that you can take back to your teams. I encourage you to include code review training in your onboarding for new developers, and to document your expectations and encourage them until they become the norm. You’ll soon see the impact this has on team health and growth.