The Downward Spiral of Slow Code Reviews and How to Fix It
I know, bold step to start a post with the assertion that you have a process problem. And you might not have one — in which case pat yourself on the back and consider yourself one of the lucky few. It’s hard to get your code review process running smoothly and to ensure it doesn’t slow down development and innovation. And even if it does run like a well oiled machine— I hope I can give you some pointers and ideas on how to make it run even better.
The blog is written from my perspective as a Frontend Developer on the Engineering team at Panaseer. I’ll mention some technologies that are Frontend specific. If you primarily work on the backend or any other Software Engineering discipline that runs code reviews — the lessons should be transferable.
The Fable of Slow Code Reviews
If you’ve worked in a Software Engineering position for a while, you’ve probably encountered this problem at some point. Let me start with a short fictional story (or non-fictional story for some teams) to illustrate the issue.
I’m having a great day — the code is just flowing from my fingers and I am finishing up changes to the architecture of a big new feature.
To let my team members know that code is ready for review, I send a message to our Slack channel — or even better our smart Github Slack bot sends the message automagically. Whilst waiting for someone to review the pull request, I decide to have a look at a bug that’s been bugging me for a while (pun intended 🤓). Since I’m having a great day this pesky bug won’t derail me, it’s a quick fix and I raise a second pull request. I’m feeling optimistic now — maybe someone added a review for the first PR already. I check Github, no review yet. A little dent in my great day, but it’s time to pack up and head home anyways.
After a good night’s sleep, I’m back at my desk with a fresh cup of coffee — feeling optimistic once again I check Github — still no reviews. I know everyone is really busy, plus I sent out a message on Slack the day before, so someone is surely about to start the review. I decide against sending out a follow-up message for now. Instead, I make a start on the next feature, which is a bigger more complex piece of work. It takes a while to understand the requirements, but after a couple of hours, I’ve fully emerged in the task.
Just when everything is starting to come together, someone taps me on the shoulder. Julian, who works on the frontend team with me, started reviewing the architecture PR and has some questions on the component interactions. I feel slightly irritated for being pulled out of my flow state just when I got into it, but it’s outweighed by the fact that someone started the review.
After a short chat, I turn back to the task at hand. The full picture of how everything fits together has certainly disappeared. Not too much later, I get a Slack message — Jacopo has picked up my bug PR and requested changes. It takes a while to go through the comments — amidst missing function documentation and trailing commas there are a bunch of other formatting changes to address. Before I get a chance to turn back to the new feature I started that morning, Julian’s comments start coming in on the architecture PR.
Before I know it, I am working on 3 different tasks and can’t focus on a single one of them. I’ll likely introduce a new bug and go home at the end of that day, utterly exhausted and frustrated because it feels like I spent the whole day running around jumping from one thing to the next.
That’s the short story of not prioritising code reviews. At the core of this is the belief that a task at the In Review stage on your Jira board is a finished task. What I am trying to illustrate, is that a task In Review is actually a task still In Progress. There are often easy ways to speed up the time to get 👍 or constructive feedback on pull requests — so why accept the challenges that come with long-lived pull requests. The longer your PR stays open, the more likely you are to take on additional work, leading to delayed value to customers and decreased productivity due to frequent context switching. At this point you might ask “How do I change that?”.
Figure out your Baseline
The first step to improving the speed of your review process is to figure out how your team is doing at the moment. Start by measuring the time code spends in specific phases of the review process.
⏰ Here at Panaseer we started by looking at the following two:
- Time from when a PR was raised to when someone took responsibility for the review and assigned themselves
- Time from someone assigning themselves to the actual review being added
There were a bunch of other things we could have measured, like the end to end lifetime of a pull request, but we found that for our team those two were the ones where we could make the biggest gains initially.
Once you have the metrics and you know what your baseline is, it’s time to start experimenting to improve the team’s review performance.
The Pull Request Checklist
Once you’ve started measuring review performance, it’s time to look at the process. Below is our checklist for making sure our PRs are not a burden to review.
№1: Automate Away!
If I had to comment every few lines on formatting and code style — I’d procrastinate getting the review in as well! Style and formatting are some of the easiest things to standardise through automation. On the Frontend Engineering team here at Panaseer, we make heavy use of eslint and Prettier. With that in place, there shouldn’t be any need to comment on formatting or style in code reviews.
The other area we automated, focussed on reminding the team of unassigned PRs and assigned ones that are still missing reviews. It’s easy to lose track of pull requests you are assigned to — having something in place that reminds you, helps get reviews in quicker. We’ve been busy, working on some Github and Slack integrations — keep your eyes peeled as we’ll be open sourcing them later this year.
№2: Take Responsibility
A pull request that doesn’t have anyone assigned to it, won’t get a quick review. Unless specifically communicated no one will plan the review into their day and take care of it. Making sure that once a PR is raised — it’s clear who is responsible for reviewing the code, is vital for reducing the PR lifetime and getting it merged in a non-disruptive way.
№3: The Pull Request Size
№4: Don’t Surprise
The code you pack into a pull request is not meant to surprise. For bigger features that involved multiple components and sometimes complex component interactions, use co-design session for the architecture of the feature or pair programming. That way your reviewer is already familiar with the code and the bar to getting a good & timely review in is lower.
№5: Give Up All the Information
Have you ever reviewed a pull request and even though you knew about the architecture of the feature, it took you some time to remember why this feature was being built in the first place? To avoid for your reviewer having to find the related ticket and relevant information manually, standardise the information you provide with pull requests. We started using Github Pull Request Templates and they’ve been helping a lot! Using templates, we can ensure that every pull request clearly states the context of the task, the actual changes, any new patterns that were introduced, what kinds of testing was added and a link to the ticket. I wouldn’t want to review a PR without it anymore! We open sourced our PR templates — if you need a starting point for yours take a look here.
Take Action on Your Team!
The best way to address this problem is to establish a baseline and start experimenting! I hope reading this you got an idea of where to start — some initial ideas to set you on the right path.
👋 Let us know what’s worked for your team! We’d love to increase the number of items on the checklist. You can reach me on Twitter at @BorriesAnton.