Costs of Blocking Code Reviews
In many companies, you can’t merge your code to master till someone has reviewed it. I’ll call this a blocking code review. Such a process has many costs that people don’t generally recognise:
Slower iterations: Sometimes you need to launch something, see how it works, and iterate again and again. For example, when you’re trying to optimise your sign up flow, you make a lot of small changes like making the Sign Up button more prominent and seeing how it impacts conversions. Another example of iterations is optimising peak memory usage, when you ideally want to change one parameter, see its impact, and repeat. A third example is debugging a bug that’s not reproducible locally: you add an assertion somewhere, see if it triggers in production, and depending on whether it does, look at a different part of the code more closely. In all these cases, you need multiple iterations. And iterations by definition can’t be parallelised. So you need to remove barriers in the way of fast iteration. Startups that iterate slowly will be out-competed.
Lower productivity: I once made 40 commits by lunch. If each had to wait for a review for just an hour, that’s a week. That’s a 14x slow down. People don’t work at a constant rate like machines, which might produce one widget an hour. They have peaks. If you cut off the peaks with rigid processes, you’ve significantly reduced their productivity.
Morale: I felt so happy about the day I made 40 commits, and still remember it. These high points are important for satisfaction. We’re not emotionless robots. Take away the joy, and your engineers will care about their job less, or switch jobs when someone offers them 30% more. I remember encountering a potential for improvement in the code and not bothering to do it because of the code review process. Make it hard, and people will not care, just as increasing the amount of money required to start a company means that fewer startups are started.
Zero-sum dynamics: Blocking code reviews create a zero-sum dynamic where the submitter would prefer an immediate review (to maximise their own productivity) while the reviewer would prefer to do it at their convenience (to reduce their context-switching and thus increase their productivity). A variant of this is a rush for reviews towards the end of the sprint, when everyone is waiting for a review, but everyone is rushing to complete their work and can’t review. I’ve seen such issues flagged to managers in multiple companies.
So, since blocking code reviews have all these problems, what can you do instead of blocking code reviews?
You can do non-blocking code reviews: engineers are empowered to merge code into master without code review. The build and tests are automatically run, and if they pass, the code is merged and goes live. Someone reviews the commit asynchronously. The logic behind this is that the majority of issues flagged during code review are not showstoppers, so you don’t need to stop launching them. And if an engineer suspects that a commit is risky, or he doesn’t understand the code well enough, he can always commit it to a branch and request a merge review. Empower engineers to use their judgment rather than putting a process in place that assumes they’ll screw it up if given the chance.
You can explore automated code analysis tools like DeepSource or SonarQube. Just be careful to pick a tool that has a high signal to noise ratio, much higher than traditional lint tools, which have a tendency to spam developers with a ton of subjective and inconsequential warnings like “No newline at end of file.”
You can attack the problem upstream of code reviews, by having written code quality guidelines that all developers follow, instead of enforcing these via code review.
You can attack the problem downstream, by letting developers deploy without code review to a canary instance that receives only a fraction of traffic. The commit is rolled out completely only after a code review.
Employ one or more of the above solutions instead of requiring blocking reviews for every commit.