Software devs, you ever get a PR review that you just cannot understand? Like a “what in the world am I supposed to do with this?” PR review?
I got one the other week.
One of those big ‘request changes’ Github reviews, but not about the code.
It was about the way I approached the problem.
I did it in a way I found to be simpler than the reviewer preferred.
Now, you might think… “uh, maybe you approached it wrong? Maybe simple wasn’t the right idea?”
To my mind, that’s asking the wrong question!
By the time code is being written, approach should already be decided.
This was an architecture argument masking itself behind a code review.
It took about 20 minutes with leadership to clear up the dispute.
But, the thing that stuck in my craw was that the code review itself was just a poor way to argue the point.
In 20-odd years of writing software, I’ve been tempted to ‘request changes’ on a code review many times.
Usually along the lines of “could this be better done in F#?” (Answer: “of course it could.”)
But my subjective opinion about one language being superior to all others is just that. Subjective.
A good code review avoids the following:
- Subjectivity
- A negative tone of voice.
Finally, a good code review process avoids the following:
- Buddy reviews – where Dev 1 approves Dev 2’s code and vice versa, despite having a larger team.
- One approver.
Avoiding subjectivity in a code review is a hard but critical skill for any senior engineer.
Being subjective or negative in a code review is often toxic, and when other engineers do not want to work with you, your impact is necessarily lessened.
Avoiding process errors keep the purpose of code review to what a code review is intended to be.
Buddies are more likely to overlook flaws in one another’s code, and single approvers are just a bottleneck.
A good code review reviews the code, not the architecture, or the tech design.
Designs can and should be argued, but unless code does not produce working software, arguing design during code review is just a waste of time.
I have five major things I like to check for during code reviews.
First, I like to automate away subjectivity.
Linting or code-formatting tools exist for nearly every language out there, and pre-commit can be used for that same purpose.
Automate the formatting, and be done.
Second, I want to confirm the functionality. Ideally with clear, easy to read tests that are present in the code.
If tests are hard to read, that is a reason to consider requesting changes.
Third, clarity and coherence. Is the code idiomatic for what it’s doing?
Fourth, I want to validate that the code, as written, is necessary.
Many frameworks are quite large and complex, and some developers can miss ‘out-of-the-box’ functionality because they did not know it existed. Sometimes, it’s worth a check.
Finally, I want to check for design flaws or edge cases.
Note, this isn’t an approach check! This is more detailed. I want to test for edge cases that the structure will expose.
So to recap, try to do the following during your code reviews:
- Automate Subjectivity
- Linting or code formatting tools are established now.
- Example: “I would have preferred you write this in F#.”
- Linting or code formatting tools are established now.
- Confirm the Functionality
- Does the code do what it says it should do?
- Example: This is just correctness. If the code says it adds two numbers, and it, in fact, multiplies them.
- Does the code do what it says it should do?
- Ensure Clarity / Coherence
- Does it fit in with the way one would expect it to?
- Example: Did they write a lot of object-oriented Python for a pandas task? Or did they use the word ‘Model’ to describe what should be a ‘View’ in an MVC app?
- Does it fit in with the way one would expect it to?
- Is it Necessary?
- Are there out-of-the-box, or framework options that do the same thing?
- Example: Did the person rewrite aspect oriented hooks, because they didn’t know Spring did that?
- Are there out-of-the-box, or framework options that do the same thing?
- Catch Design Flaws.
- Are there edge cases the current structure will expose?
- Example: Do the types allow for data that are not tested? (Strings and ints do this a lot, as people don’t plan for an Int32.MaxValue regularly.)
- Are there edge cases the current structure will expose?
Hope this helps!










