In this article, I outline organizational best practices for creating quick and painless code reviews.
I recently had a conversation with a friend of mine about code reviews.
Code Reviews in his organization were long and painful.
The reviewers frequently had strong and differing opinions about implementation.
I have been party to scenarios like this before. They are no fun.
I left this conversation wondering what a good code review process looks like.
How can we create systems that refine new code without unnecessarily obstructing work?
After all, software engineers are paid to advance business goals, not write squeaky clean code.
Here are a few best practices I have found dramatically improve the code review process.
1. Define what Good Code looks like for your team
As a team, collectively think about what Good Code looks like.
Is Good Code the same as Tested Code? Or should it just be Testable Code? Does test-ability not matter?
In their earliest stages, a startup’s definition of Good Code state:
On our team, we strive to write working code that is: - Testable - Secure (no public s3 buckets please!)
Notice how there is no mention of
Tested code here.
Every team will need to decide this for themselves. It is entirely possible though that taking the time to write tests does not align with an early-stage startup’s business goals.
However, if you write code with testing top of mind and break down components and functionality accordingly, adding those tests later will be significantly less painful.
As the company grows, the team’s values might evolve into the following:
On our team, we strive to write working code that is: - Testable - Secure - Tested - Reuseable - DRY
This list still conspicuously lacks any mention of performance.
For many small companies code performance is simply not a concern. As long as it qualifies as “working code” fine tuning performance may not matter.
Imagining our startup grows into the next AirBnb, Dropbox, etc, the entire conversation changes.
An example of their code review principles might run as follows:
On our team, we strive to write working code that is: - Testable - Secure - Tested - Reuseable - DRY - Revertible - Performant
When a team clearly defines and adheres to these principles everyone can write and review code from a common starting point.
This makes reviews infinitely smoother, faster, and more pleasant.
The author of the code knows what is expected of her/him and can write code accordingly.
Additionally, you can drop in anyone from the team as a reviewer and come out with consistent results because the review is driven by principles rather than opinions.
This greatly reduces the potential for a scenario where John submits a PR and then receives conflicting feedback from Senior Joe and Senior Jane.
However, we can go a step further mitigating the risk of these scenarios.
2. Encourage Design Discussions Between Authors & Reviewers Before Executing a Task
This applies most to early career engineers but can be useful for every team member regardless of seniority.
When a sizable new feature or code component of reasonable size needs to be built, encourage the author to have conversations about design with the technical stakeholders who will eventually review the code.
By having these discussions early on the author can establish consensus on a design approach early on in the development process.
Once technical stakeholders buy in to a design, the author can then hold them to that later in the review process if they raise deep issues around the design that would require a significant rewrite.
Perhaps most importantly to the author, this decreases the likelihood of being asked to go back and rewrite large swaths of code.
I have seen these principles dramatically improve the speed at which code moves from conception to production and hope that they can help you and your teams as well.
If you have additional thoughts on these topics I’d love to hear from you. You can find me at (twitter)[twitter.com/jonathanwmeier).