Code Reviews: The Definitive Guide
Many developers have a love-hate relationship with code reviews.
We love the fact that they help us improve our code quality and our skills, but we hate it when they are done poorly and become painful experiences.
In this guide, I’ll give you everything you need to conduct or navigate through a code review successfully.
Let’s get started!
Section I. Code Review Basics
Chapter 1: What Is a Code Review?
In a nutshell, a code review is an evaluation method used to identify errors in code during the software development process.
Code reviews should reveal and remove bugs, help make the code base sustainable long-term, and build developer skills and self-confidence.
Chapter 2: The Code Review Process
Code reviews are very much like the editorial or copy review process that companies creating customer-facing content have in place to ensure content is produced free of defects, aka typos.
The code review process varies from company to company, but at a high level, it goes something like this:
Step 1: The Code Review Request—the author or developer who wrote the code makes a request and submits code for a code review.
Step 2: The Code Evaluation—the reviewer, usually another developer or quality assurance team member, reviews or evaluates the code submitted. This is where errors and other issues are identified.
Step 3: Approval and Feedback—once the reviewer has identified any errors and issues in the code, they provide feedback to the author. This is generally where the code in question is either approved or rejected.
Step 4: Developer Action and Acknowledgment—the author reads the review, acknowledges any feedback given, and takes action (if necessary), making any required changes to the code.
Chapter 3: Benefits of Code Reviews
Benefit #1: Code Reviews Save Time and Money
Code reviews are important because when errors are uncovered early on, companies can save a lot of time and money. It’s less time-consuming and less expensive to fix bugs before software is released.
An IBM study revealed that bugs fixed later in the software development lifecycle were significantly more expensive to fix than bugs fixed early on.
In fact, the study found that bugs fixed during the testing phase were 15 times more expensive to fix. It also found that bugs fixed during post-production were 100 times more expensive.
Benefit #2: Code Reviews Can Prevent Bad User Experiences
I have become a fan of programmer humor. The killer robots comic reminds me of how important code reviews are to avoid unintended outcomes and bad user experiences.
Here’s a personal example of this for me.
I found a really amazing artificial intelligence logo creation tool that I fell in love with. I was able to create beautiful logos quickly at reasonable prices.
I created and purchased a few logos from them, and then one day, I created a logo and received error messages in the middle of the process.
I started the logo creation process over and the same thing happened. Frustrated and disappointed, I ended up going to one of their competitors to create my logo.
The logo I created with their competitor’s tool wasn’t as nice as what I was in the middle of creating, but I was at least able to create and purchase a logo without encountering error messages during the process.
I didn’t leave the company a negative review, but my use of their tool has decreased dramatically. A while back, they asked me to join their ambassador program, which I did, but I cannot bring myself to promote them because of this negative experience.
If this happened to me, I’m sure it happened to other people.
Experiences like these cause companies to lose out on sales at hand and future sales, since customers will be hesitant to trust that the product actually works the way it’s supposed to.
Companies also lose out on sales from a lack of customer referrals, which don’t occur because of the negative experience.
When I made my first logo with them, I told everyone I knew and recommended them.
When I had the negative experience, I mentioned them, but was honest about my last experience. I told my friends and colleagues about their competitor that I didn’t like as much, but that I felt was more reliable and could produce a high-quality product.
From a reputation and market position perspective, it’s better if development teams catch their own errors in code reviews than for end users to catch them.
Usually, when customers have negative experiences, they complain about them to the world on social media and through negative reviews. These complaints have a negative impact on current and future sales of the product.
Benefit #3: Code Reviews Can Build Stronger Teams
Code reviews are so much more than catching and fixing errors. When done right, they can strengthen the skills and increase the knowledge of development teams.
A 2013 study at Microsoft revealed that even though the main purpose for code reviews is to find defects, other benefits that developers look for and expect from code reviews include:
- Knowledge transfer
- Increase in team awareness
- Development of alternative solutions to problems
When development teams work together and are able to share knowledge, expand their problem-solving capabilities, and become more aware of each other’s strengths and weaknesses, they have a foundation to build stronger teams.
Section II. How To Conduct a Code Review
Chapter 4: Reveal and Remove Bugs
As mentioned earlier, the primary goal for any code review is to reveal and remove bugs. As the reviewer, your job is to uncover mistakes that the author/developer made while writing code and prevent them from going into production.
The following is a list of common errors to look out for when conducting a code review.
- Logic/Semantic Errors
Logic or semantic errors are bugs that cause your code to produce outcomes that you did not intend to produce. Because the code actually functions, logic errors can be the hardest errors to detect.
Here are a few examples of logic errors:
Here’s another simple, yet cute, example of a logic error:
The code above works, but the poor penguin was programmed to turn the wrong way and hit a wall!
- Runtime Errors
Runtime errors are a category of errors that appear once you’ve run your program.
When the program is run, the end user will see an error message. Logic errors are included in this category.
Runtime errors are often triggered by user input that is illegal and where there is no program for what to do with the input.
Types of runtime errors include:
- Memory Leak—causes a program to use more RAM while the program is running
- Program Crash—happens when a program stops running (can be caused by memory leaks or programming errors)
- Division by Zero—happens when a user inputs a zero in the denominator field
- Logic Errors—occurs when your code produces unintended outcomes
Below is an example of a Division by Zero runtime error:
When the value 0 is used for int b, the runtime error message generated is a Division by Zero error message.
The way to handle this is to plan for this scenario occurring.
Below is a way to plan for this in C# using a try-catch block:
- Syntax Errors
Syntax errors occur when you don’t follow the rules of the programming language you’re working with.
- Mistakes in punctuation
- Typos (including adding or leaving out symbols)
- Spelling errors
- Incorrect indentation
- Empty block
- Keyword errors
- Incorrect use of letter case
For languages that use a compiler, syntax errors are detected at compile time, and the program won’t run unless the syntax errors are corrected. These types of errors are easier to catch by the developer/author.
For programming languages that use an interpreter, syntax errors aren’t detected until your program is executed.
Depending on the type of interpreter, there may or may not be a lot of useful information about the type of error that exists within your code. Code reviews are helpful in these situations.
Typos are an example of a syntax error that you should look out for in a code review, since they are very easy to make and won’t generate a syntax error while writing the code.
As you’re writing code, you could easily hit a character, like the “=” sign, one too many times or not enough times, and your program will end up producing a result you hadn’t intended.
Result when run: true
What you actually typed was a strict equality:
Result when run: false
It’s really easy to hit a keystroke one too many times, and in this case, the code itself isn’t wrong from the interpreter’s perspective. So unless you run the code or a reviewer sees that it deviates from your requirements, you won’t know you made this error.
Chapter 5: Ensure Your Code Is Readable, Maintainable, and Secure
Another key component of code reviews includes making sure the code is readable, maintainable, and secure.
Imagine picking up a book—physical or digital—and it looked like five different people wrote it without knowing the other four people were writing it, too. They each used different font sizes and font types. Each of them had their own unique way of using indentation and white space.
And to make matters worse, they each had their own linguistic style and voice. This book would be an absolute nightmare to read.
Now, imagine looking at a code base that looks like several different people wrote it.
Different people using their own unique style, formatting rules, naming conventions, and comment rules.
Even if the code is functional, if it’s difficult to read, it will be difficult to maintain.
On top of all this, imagine that security vulnerabilities exist throughout the code, which could have a negative impact on your company or customers. Double nightmare.
Therefore, your development team must determine your best practices and stick to them. Here are a few areas that should be included in your code review, which will help ensure your code is readable, maintainable, and secure:
Readable code has clear and meaningful naming conventions, includes meaningful and succinct comments, and is visually appealing.
Names should reveal the intent of your code.
Whether you’re naming a variable function or class, the name should tell you and other developers reading or reviewing your code “why it exists, what it does, and how it is used. If the name requires a comment, then the name does not reveal its intent.” (Source: Clean Code)
Here’s an example from Clean Code:
In the above code, Robert C. “Uncle Bob” Martin makes a point that it’s hard to tell what the code is doing. The code itself is simple enough, and it’s not hard to read from a formatting perspective.
The code doesn’t offer us important information like what things are in the list, why the value of 4 is significant, and how the list being returned will be used.
Uncle Bob offers this code as a better alternative. He provides more context, offering the assumption that the code is part of a Minesweeper game.
Some changes that he made to the code were renaming key items that were vague, making them more specific, and communicating/providing more information than the previous version.
He changed “the list” to gameBoard, since, in the context of a Minesweeper game, the game board is the list of cells.
He also changed the value of 4 to flagged cells to reflect the value’s true meaning.
These changes to the code communicate the intent better than the previous code, which would require comments to help another developer (or even the same developer in the future) understand or remember what the value of 4 represented or what “the list” was.
There are many opinions on using comments in your code. Some developers feel that good, clean, elegant code doesn’t need comments. Others believe that comments are useful and necessary. I am relatively new to the field, and for now, at least, I think that code should be written in a way where it can stand on its own without comments. However, there are situations where comments are necessary.
Comments should be used sparingly, only when the code itself can’t be expressive enough. They should be used when they add value and help developers understand what’s going on more quickly than if the comments weren’t there at all.
Comments should not be used to explain naming conventions.
It’s better for everyone that the names themselves be improved instead of creating comments that explain them.
Also, comments should not be redundant. Below is an example of where a comment is not needed. The code explains itself.
When writing comments, keep it simple. Avoid anything that won’t be useful to you when you work with your code in the future.
Also, avoid anything that won’t be useful or that could be disruptive (such as mean comments or bad jokes) to your team when they work with your code.
For those instances where you’ve written code in the most expressive way and adding comments will add clarification and save everyone time, write good comments.
What are the characteristics of good comments?
Comments should be succinct. They should convey the greatest amount of information with the fewest possible words. Here’s an example from The Art of Readable Code for a C++ type definition:
The comments in the second sample are a lot more efficient than in the first sample.
In your code reviews, if you see comments that are unnecessary or poorly written, make suggestions to either remove or rewrite the comments.
Another component of readable code is formatting. Good formatting makes code easier to read and easier to work with. Teams should agree ahead of time on a formatting style and stick to it, and your code review should check to make sure the style is being followed.
When it comes to establishing formatting best practices, you should:
- Be consistent
- Choose a style that makes your code easy to understand
- Use white space that makes your program easier to read
- Decide ahead of time to use tabs or spaces
- Follow predetermined capitalization rules
In addition to checking for readability, code reviews also need to make sure the code is maintainable. Developers spend a lot of time maintaining code. The more maintainable the code is, the less time it takes to do maintenance work.
Here are a few questions to ask when conducting code reviews regarding maintainability of code:
- Will the code be easy or difficult to make changes to down the road?
- If changes are made, will they have a positive or a negative impact on the code base?
- How searchable is the code? Is the code written in such a way that makes it easy to find what you’re looking for?
- Will it be easy or hard to find and fix bugs the way the code is written?
A critical component of the development process is security. To protect your company and your customers from hackers, security should be part of the code review process and conducted whenever necessary.
Because this is such a huge topic, an entire blog post could be dedicated to it. For our purposes, I will focus on two common security issues in web development:
- SQL Injection
- Cross-Site Scripting (XSS)
An SQL injection is a common method of hacking where malicious code is injected into your database through SQL statements that are entered into your web page.
Here is an example:
SQL Injection Based on “”=”” is Always True
User login on a website:
It’s possible for a hacker to gain access to user names and passwords in a database by inserting ” OR “”=” into the user name or password text box.
The following is the resulting statement on the server:
This statement is valid and will return all rows from the “Users” table, since ” OR “”=”” is always TRUE.
Using SQL parameters, programmers can protect a website from an SQL injection.
Parameters are represented in the SQL statement above by the @ marker.
This parameter will prevent hackers from accessing data in the database. Other SQL parameters can be found here: https://www.w3schools.com/sql/sql_injection.asp.
XSS are also injections. However, in this case, malicious scripts are injected into websites versus being injected into SQL databases.
Malicious code is sent through a web browser script to website users’ browsers to gain access to users’ browser data contained in cookies, token sessions, etc.
XSS attacks are more complicated than SQL injections, because they affect website users as opposed to affecting a database. This makes XSS attacks harder and more complicated to address.
There’s also no single way or protocol available to prevent these attacks, unlike being able to use SQL parameters to address SQL injections.
Because of the complexity of XSS attacks, I have listed some helpful resources that you can reference and consider incorporating into your code reviews as opposed to referencing specific examples and snippets of code.
Helpful XSS Links
Code reviews for websites and other applications with databases that can be hacked should include an evaluation of security vulnerabilities and programming strategies to eliminate security risks.
Section III. How To Avoid Code Review Failure
Chapter 6: Reasons Code Reviews Fail and Tips to Avoid Failure
The ultimate failure is allowing bad code into production.
However, there are other things that can cause code reviews to fail.
Code reviews that demotivate developers and don’t offer valuable feedback that will help them grow as programmers are failures.
The long-term effects of bad code reviews can have negative impacts on development teams.
There are many reasons code reviews can fail, but here are a few that stand out:
Reason #1: Communication Breakdown Between the Author and Reviewer
This is probably one of the biggest reasons code reviews fail.
If the author is not open to feedback and has their way of doing things that may not align with how the reviewer thinks they should be done or that doesn’t align with team best practices, there will be a communication breakdown.
If neither side comes to an agreement or understanding, the code review will fail, and the relationship between the author and reviewer will be strained.
Likewise, if the reviewer isn’t skilled in giving feedback in a productive way and comes across as condescending or rude, the code review will fail because the feedback won’t be received by the author due to poor delivery.
Tip to Avoid Failure Caused by Communication Breakdown
As the reviewer, offer feedback that is crystal clear and free of unnecessary or rude comments. When in doubt, have someone review your comments before submitting the review.
As the author, be open to constructive feedback. Consider how another approach can help improve your craft.
Reason #2: No Agreed-Upon Objectives for the Code Review
If code reviews are not based on common objectives that are agreed upon ahead of time, the reviewer will use their own objectives in the evaluation.
Those objectives may not align with what the author had in mind, especially if they were the one who requested the code review. When there are no preset objectives, there is a lot of room for conflict and communication breakdown.
That said, there are high-functioning teams that take a more informal approach and have unspoken, agreed-upon objectives. This is fine as long as there are no changes to the team.
However, we know that change is inevitable, and as the company grows, the team will grow and new people will be added to the team.
Tip to Avoid Failure Due to Having No Common Objectives
Take time to establish agreed-upon code review objectives. Document and share them with the entire team. Review these objectives with new team members so that everyone is on the same page.
Reason #3: Unwillingness to Change or Grow
As adults, it’s really hard for us to make changes in our behavior and grow, even though we know change and growth are good for us in the long run.
If authors consistently get feedback from code reviews that could make the way they approach programming better and they don’t put it to use, these code reviews are failures.
They’re failures because these programmers haven’t taken the opportunities they have been given to grow.
They’re also failures because reviewers, who may be providing this feedback time and time again, can feel like they are wasting their time. As time goes on, they may not be as thorough if they feel their suggestions are falling on deaf ears.
Tip to Avoid Failure Due to Change and Growth Resistance
Open your mind to the adventure that change can offer. If you keep doing the same things over and over, you’ll get bored and you won’t grow. If you try something new and it doesn’t work out, that’s fine. You learned something. But always be on the lookout for ways to apply the concept of innovation to your own work.
Chapter 7: How To Handle Abusive Code Reviews
When I first came across this comic, it made me laugh. And then I thought about it, not just in terms of measuring quality code, but in terms of measuring the quality of the code review.
WTFs are hilarious in the comic, but not so much when you’re the author and you feel that you—as either an individual or a programmer within the context of code reviews—are being attacked.
The best way to handle situations where reviewers leave WTFs and other rude comments is by facing the situation head-on in a calm, professional, yet direct manner.
Let the reviewer know that you value feedback that comes from the code review process. However, when the code review is filled with remarks that can be received negatively, it’s really difficult to extract the value from the review.
Remind them that you are on the same team and should want the same thing: to deliver the best product to market and to build a sustainable code base.
If that doesn’t work, you may need to escalate things to your manager. But you should never allow someone to use the code review process to be rude or condescending toward you.
Section IV. Summary: Code Review Checklist
When doing any type of review or quality check, it’s always nice to have a handy checklist to refer to. Below is a checklist that summarizes all the key points in this post. Feel free to use it as you’re conducting your own code reviews.
|Item #||Code Review Checklist|
|1||Reveal and Remove Bugs|
|Check for common errors such as:|
|2||Ensure the Code Is Readable, Maintainable, and Secure|
|Is the code readable?|
-Consistent style used throughout
-Consistent use of white space
-Consistent use of tabs and spaces
|Is the code maintainable?|
|Is the code secure?|
-If yes, follow your company’s guidelines for conducting a security code review
|3||Incorporate Soft Skills to Avoid Code Review Failure|
|Is your communication clear and respectful? Will your review add value to the author?|
Section V. Conclusion and Resources
After reading this post, I hope that you’ve become an even bigger fan of code reviews. I also hope that it has sparked some ideas for things you can include in code reviews that you conduct. Below are some resources you will find helpful.
Good luck and happy code reviewing!
If you have any ideas that would add value to this post, feel free to leave a comment.
Resources for Conducting Quality Code Reviews
- Clean Code by Robert C. Martin
- The Clean Coder by Robert C. Martin
- The Art of Readable Code by Dustin Boswell and Trevor Foucher
- How to Win Friends & Influence People by Dale Carnegie
- The Power of Habit by Charles Duhigg
- OWASP (Secure) Code Review Guide
- How Not to Run a Code Review
- What I Learned From Failing My First Code Review
- XSS Attacks
- Reviewing Code for Cross-Site Scripting
- Cross-site Scripting
- 3 Ways to Prevent XSS
Podcast Episodes and YouTube Videos