There are a lot of benefits to working with a good team, and code reviews might be my favorite. When done right, they not only increase code quality, but they also help your bus factor and offer a fantastic opportunity for both reviewees and reviewers to grow and learn new things.
I was totally hooked on code reviews after working with a great team that required in-person reviews for every change, but that didn’t last forever. In my next venture, I found myself in a very different situation: I worked solo for several years, with no peers to review my code at all.
I was determined not to lose the benefit of code reviews entirely, so I decided I’d do my best to review my own code. I got in the habit of carefully scrutinizing my own diffs before committing and pushing. Now, it’s a habit I’m very thankful for. Even though I now work with another great team, I’ll never stop reviewing my own code.
Why do self-reviews?
Why review your own code even if you have peers to do it for you? There are some small benefits: your code gets merged faster and you maintain a cleaner commit history. But the biggest reason is that it makes those peer reviews, when they happen, much more valuable.
If your code contains simple mistakes, style violations, and other ‘easy stuff’ when it gets to your reviewer, their time and energy is wasted on pointing out those things you (or a robot) should’ve caught. Handle all of that stuff beforehand. This allows the reviewer to focus on things that require their expertise in the code, business domain, and system architecture. It leads to better software, and it also improves the reviewer’s experience. Instead of acting as your linter, they’re offering valuable input, which will encourage them to put more energy into future reviews as well.
How to self-review?
How do you review your own code? If you could catch your own mistakes, you wouldn’t have made them in the first place, right? I’m not trying to diminish the value of a fresh pair of eyes, but I’ve found that I can catch a lot by deliberately changing my own frame of mind.
Here are a few different lenses I like to use when reviewing my own code. On a small diff, it may be enough just to keep these things in mind while reading through the changes. For something larger, I’ll make several passes through the diff. And I’ll focus my attention on a single lens all the way through.
- Easy stuff – Revert files you didn’t mean to / need to change, remove debug statements and dead code, fix style issues. Are there TODO comments you forgot to address or remove?
- Regressions and side-effects – Look at each change and ask yourself, “Is there any conceivable way this could break other parts of the system?”
- Correctness – Make sure the code really does what it needs to do, and that you have tests to prove it. Pay attention to branches and corner cases you might not have tested thoroughly.
- Quality – Is the code easy to read and understand? Did you choose the best names and organize things as cleanly as possible? Is there any tricky logic that could benefit from a comment?
When you break it all out like this, it also reinforces the value of self-review. If a peer reviewer has suggestions for you in each of the first three areas, they may not end up thinking much about the quality lens at all. I’ll just let that sink in for a minute…
The self-review is also a good way to incrementally push yourself to get better. I try to look for patterns in my code reviews with peers. If they’ve made the same kind of suggestion (e.g. “This function could use a better name.”) more than once, I can keep that in mind during future self-reviews. If I fix that class of issues myself, the reviewer can help me out with something new next time.