Code Review Process
My friend Dylan Garcia asked me: "how do you generally approach code reviews? what's your mindset? do you have a checklist?"
I've been doing code reviews for over a decade.
My process has changed over time.
This is my process as it is currently.
My Process for Code Reviews
There are 3 main goals of a code review.
The goal most people will be familiar with is to make sure the code that lands in production is as safe and correct as possible.
The second goal is to learn more about the style and decision making process for the person for whom I'm doing the review.
The third goal is to learn something and teach something.
I do my reviews in 3 stages and 3 passes.
- Pause - This is to orient me towards the person requesting review and towards curiosity.
- Explore - Review the code, attempting to be curious and noticing any judgment or suggestions that come up
- Suggest - Review the code again, adding comments for noticings and suggestions
Stage 1: Pause
This stage is about orienting, I don't look at the Pull Request.
Here are the steps I take in this stage:
- I orient myself towards the person I’m doing the code review for. What do I know about their style? What do I know about their goals? How do I get into a mindset of energetic collaboration.
- I place myself. How am I feeling outside of this code review? What have I experienced today? What are my feelings? I put anything that comes up in a note in Obsidian as a container and attempt to detach extrensic experiences and feelings from the review. This is important so that I don’t bring it with me into the review)
- I orient myself towards curiosity. I want this review to start from curiosity. In tech, so much of what we have been taught matters is defensive and judgmental. It's not to say there isn't a place to assess the code and make suggestions, but the goal of this step is to reduce my ego as much as possible.
Stage 2: Explore
This stage is about going on an adventure in the Pull Request!
In this stage, I take these steps:
- I orient myself towards the goal. I read the description. I attempt to rephrase it so I understand it. If any questions come up, I first verify they're not "suggestions disguised as questions" and if they're curious questions, I write them down.
- I read the code a first time, starting at the top of the PR. I try to understand what's happening. I don't make notes. I don't add any comments. I just try to understand what is happening. I hold the code lightly. I notice places where I hit drag in reading. Usually drag indicates something isn't clearly. If I notice I hit drag, I write questions from curiosity about the drag. I make notes of if something came up as a noticing, judgment or suggestion but I don't add them to the Pull Request. I will make a note of where I think the execution context is at the end of the read for stage 3.
- I read the code a second time, starting at the top of the PR. In the second run, I look for what wasn't clear on a first read. I look to my questions I wrote down. If they're related, I make them as comments. Any comments I add as questions to a review, I start with ❓ so they're easier for me to find later. I review the execution context I guessed on the first pass.
At this point I take a 15 minute break and do something else.
Taking a break allows my subconscious to sit with my two passes through the code.
Stage 3: Suggest
This stage is where I make suggestions based on my noticings of drag.
Here are the steps to my suggestions:
- I read the code a third time, starting at the most obvious entrypoint to the execution context. At this point, I've seen the code twice and am oriented towards what it's doing.
- I make suggestions where the intent is clear. I make suggestions in three cases: a fairly obvious security issue, a way to make the code more readable without sacrificing performance, performance benefits that don't reduce readability. In these cases I try to be really clear about what I noticed, which of these buckets I'm making a recommendation for and why I think the recommendation could make it a little better.
- Notice where someone did great work! I try to notice where I appreciate that the requester has done something that crushes for me and tell them I appreciate it and why. I think this has 3 benefits. 1. They get a dopamine hit. 2. I get a dopamine hit. 3. I reinforce what I think matters in a codebase.
Some Quick Tips
- Use Loom for comments. Add text to your comments, but also if you can, use a loom here and there and in the comment for the review. Looms help set emotional context for the person you're reviewing for.
- Stay curious. This code is about a thing someone put effort into. Recognize that they put their energy into it, be grateful for that and ask yourself how you help amplify their efforts instead of snuffing out their energy.
- Use emoji for comment types and share your heuristic. Emoji at the beginning of a comment (for example: "❔ I noticed I slowed down when reading this bit of code and I think it's because I don't understand what it's supposed to do, can you give me a summary of what you were trying to achieve with it?"). Emoji makes your comments easily scannable for both of you and helps set context for the comment.
- Set navigation points in comments. This is hard to do, but it's always been well received when I do it. If you want to create a narrative about your review, use comment hyperlinks and document them in each comment for back and next. This helps the person you're reviewing for understand the narrative instead of having to go top to bottom.
The most important thing to notice here is that I attempt to do two passes of a code review before making suggestions.
This keeps me curious about what's happening and I think when I follow this, the experience is usually really positive for me and the person I'm reviewing the code for.