10 Reasons Why Code Reviews Make Better Code and Better Teams
When I started my career in programming, I wasn’t aware that something like a code review even existed, nor did I know about its benefits.
Back then, it was just me and another developer. My coworker and I just wrote code all day long, testing it ourselves and getting it to a staging and production environment as soon as possible.
Nobody looked over my code, and I almost never read any of the new code my coworker produced. I didn't even know that developers in other companies regularly perform code reviews.
Only a few years later when I moved to another company and team, I learned why and how to perform code reviews. After some time, I started to realize their tremendous value.
While some may believe that code reviews aren't necessary, from my years of experience, I've discovered that there are a lot of benefits.
Let's have a look at the 10 most crucial benefits your team gets when you have a code review as a separate step in your development process.
1) Double-Check if Requirements Are Fulfilled
When you get a task to develop a new feature, first make sure you understand the requirements before you begin coding.
As you work on the project and hack out your solution, you are focused on getting the new feature implemented. But you might forget about one or two requirements which seem to be not so important for the task at hand.
When you finish your task, you create a pull request and assign the task to a coworker for code review.
Your coworker obviously needs to know what your task is about; therefore she needs to check the requirements of the task.
Since the team works with Scrum, she will usually remember the goal of the task because the whole team discussed it during the refinement session and/or sprint planning session. In case she doesn't remember exactly, she will check the description and acceptance criteria of the task in your bug-tracking tool.
When she realizes that a requirement is missing, she gives a kind comment on the pull request, throwing it back to you to fix it.
Arguably, the missing requirement would have been found by the tester in the testing phase as well. However, there are some requirements that are much easier to verify in the code, e.g. proper handling of errors, which are hard to produce during testing.
So, having this four-eye principle in place in the form of a code review prevents the incomplete feature from making it to the next step in the development process, or even to production.
2) Fewer Bugs in the Code
On my previous team, we had a lengthy discussion about the order of the steps in our development pipeline. To ensure the quality of the code is high, should we review the code first and then do the peer testing? Or should we do the peer testing first and the code review afterwards?
We finally decided to do the review first, and only after the review passed do the testing. This is because it is easier to spot defects during the code review than catch them during testing.
Even though this worked well for us, I also think this might be different for other projects and teams, depending on the team structure and project complexity, among other variables.
Some defects introduced in newly-written code are very hard to catch by the tester. Especially when it comes to asynchronous code, with different callback times in the test environment than in production environment.
Such defects are much easier to spot by looking into the code during a code review. For instance, let's say you review a few lines of code, which perform two asynchronous calls to a server at the same time. The code is written in a way that assumes that the first callback always finishes first. However, if the second callback finishes first, the code would break and give an error.
During testing, it might be the case that the first callback would indeed always finish first and you would never experience that error. And when you deploy that code to its production environment, which has a different setup with different callback times, you suddenly run into this bug.
Such race conditions are hard to detect during testing. However, an experienced developer is much more likely to spot such defects during a code review than during testing.
If you have code developed by a junior and reviewed by a more experienced developer, then the experienced developer makes sure that the code has a certain quality before it is checked in to the master branch.
The focus of a junior developer is to implement the happy flow of a given task, while the more experienced developer also thinks about edge cases.
During the code review, the senior engineer will make sure that those edge cases are properly handled in the code too.This assures that you never have code in your master repository that does not meet some basic quality standards.
But even if the code of a senior developer is reviewed by another senior, the reviewer will often find defects because he looks at the code from a different angle, and therefore is able to spot issues that the coder didn't think of by himself.
The point here is that during a code review you can find issues in the code that you would not find in the testing phase. Therefore, having a code review in place reduces the number of bugs in the code base.
3) Improved Code Readability
During the course of my career, I read quite a few books about programming. If I would have to create a ranking of those books, then my first choice, without any doubt, would be Clean Code from the famous Uncle Bob.
I highly recommend this book. When I read it the first time, I had already been coding for a couple of years, yet this was a tremendous eye-opener for me.
The most interesting conclusion I recall from the book was: If you have to document your code, then there is a high chance that it is already bad code and you should refactor it.
Each line of code you write has to be maintained. There is a very high chance that in the future, somebody will have to stare at your code and try to understand what it is doing.
That person might even be you twelve months from now.
Some people have the opinion that it doesn't matter how your code is written as long as it works, but this is not true. Badly-written code has a much higher maintenance cost than clean code.
It is not only a pain to review or maintain badly-written code, it also takes longer to change since it will be more error-prone.
However, writing clean code is not easy, but it is a skill which can be learned over time. If you have someone in your team who is able to write nice and clean code, it is a pleasure to read and review such code.
When you are “allowed” to review such code, you can learn from that person and become a better programmer over time. He can teach others to become better programmers by giving suggestions when reviewing their code. And people will also learn while they review his clean code.
Altogether, by performing regular code reviews, the whole team will be able to write more readable and maintainable code over time.
In some teams, only the more experienced developers are reviewing the code of their peers, and junior developers are not reviewing any code at all.
Unfortunately, those teams think that letting a junior review code doesn't add any value to that pull request, because the likelihood that a beginner will spot a mistake of a senior is rather low. It is better to let the junior spend time on something more valuable than performing a code review.
That's not wrong, because in my experience, it is indeed rarely the case that a junior has any comments on the code written by an experienced developer. However, there is still the knowledge-sharing part, which is important here: a junior developer can learn a lot from a good pull request, even though he does not have any comments for improvements.
But this is not only important for junior developers—senior developers can also learn a lot by reviewing code. Especially when you are joining a team as a new team member, no matter how many years of experience you already have in the field, you can always learn a ton from a good pull request from your experienced coworker. For example, you will learn:
- about the architecture of the application.
- in which class libraries to put which type of code.
- naming conventions.
- the conventions of structuring code within a class.
- where you can find certain logic that you might need in the future.
The last point especially can help tremendously and boost your start-up time when you are new to a team or a project.
Performing regular code reviews will quickly help you get an overview of the existing code in the repository of the project—and, you will learn which parts already exist and can be reused when you work on your own tasks.
5) Style of Code Becomes Similar
I am coming from the .Net world, and Microsoft produces new frameworks and new features in the C# language on a regular basis, even though it is not as often as, for instance, in the PHP world.
Therefore, there are often very different ways to write code—different solutions to the same problem.
Just a few days ago, I was reviewing some code of my coworker who is quite new to programming in C#. In a certain part of the feature, he had to transform a list of objects to another type and put it into a new list. He went for the straight-forward way: define the new list, create a for-loop, create the new objects within the for-loop, add them to the new list, and return the new list after the loop.
That's, of course, a valid way, but I showed him a new, more elegant way by introducing him to LINQ (Language INtegrated Query). LINQ allows you to solve the same problem with just a few chained statements, and therefore the produced code is shorter and more expressive.
Without that code review, he would still be solving such problems using his old approach. This is not wrong and it would work perfectly fine, but a more experienced developer will scratch his head and recognize that this lengthy code has been written by someone who doesn't know this C# language feature.
But from now on, because of the code review, my coworker is going to use LINQ to solve such problems, as everyone else in the team is doing as well.
This shows that code reviews help to maintain a similar coding style in your code base.
6) Removes the Single-Point of Failure
Imagine for a moment a team that does not have any code reviews.
I believe the following will naturally happen:
A new feature is developed by a certain guy. A couple of weeks later that feature needs to be extended and gets more and more functionality, growing into a separate component. If there are new requirements for that component, that same guy will be assigned the task because he is the expert in that component.
Now this goes on for a couple of months or even years.
The component has evolved and a lot of new functionality has been added. And those additional features have always been added by the same guy because he already had all the domain knowledge. And he also knew where to place the new code because he built the original structure.
Of course, that guy will probably be the most effective and can finish the new feature the fastest. As he wrote the existing code by himself, he doesn't have to spend time figuring out what it is doing.
If you don't have code reviews in place, then this is exactly what will naturally happen with a team. Everybody is going to have a piece of software that he wrote by himself, and nobody else has ever seen that code.
Obviously, the big problem here is that the expert might not be available. For instance, the expert is on holiday for three weeks, or he gets sick. Or maybe he decides to move on and find another job somewhere else.
What happens if the expert is not available and you encounter a serious bug in the application? You have the problem of a single-point of failure. It will take the rest of the team quite some time to go through the code that nobody has ever seen before and find the bug.
Now, imagine if you have not only one of such a component expert, but your whole team consists of experts—each team member is the expert of a certain component. Then you have not only one single-point of failure but a couple of them.
However, if the team has code reviews in place, you remove the single-point of failure because the knowledge is spread over the team.
Of course, the expert would probably be the guy to go for fixing a bug or developing a new feature request. But if the expert is not available then the team will make up for it, because they have already seen the code during reviews and know what is going on in that component.
7) Better Estimates and Better Planning
Many teams use Scrum as their working methodology. In Scrum, you define so-called user stories to split up desired features of your software into manageable pieces of work.
Scrum also describes a refinement meeting, in which the whole Scrum team comes together to discuss those user stories and finally give an estimate on how much effort is required to implement the feature.
These estimates are gathered through planning poker, where each team member can vote on how much effort, quantified in story points, the user story will be. The consolidated estimations are then used for further planning and prioritizing of the next features the team is going to work on.
This means the better those effort estimations are, the better the future planning.
So, what can you do to improve those estimations?
Well, let's assume the team wants to estimate the effort of a new user story. This new user story is about extending an existing piece of software with a new functionality.
If only one person wrote that existing piece of software and nobody else in the team saw the code, it is quite hard for the rest of the team to give a good estimate.
However, the more people that saw some pieces of the code during a code review, the better the estimates will be.
That's why having code reviews in place also increases the accuracy of these estimations. The better the estimations, the more accurate the plan will be for when a certain feature will be finished.
8) Improves Code Quality by Peer Pressure
I remember when I was part of a team that did not do proper code reviews. Back then, I was writing and testing my code, and when I saw it working I checked it in. With this approach, a lot of mistakes could slip through and make it to production, and we had to fix those bugs later on when they were reported by our customers.
Nowadays, there is one more step I do before I create a pull request for my coworkers to review: I compare every single line of change that I made and make sure that everything is clean and tidy. I remove stupid comments and rename variables, methods, and classes to make it absolutely clear what it does. I even remove empty lines that are not necessary to make the pull request easier to review.
And sometimes, when I stumble upon some piece of existing code that is poorly structured or named, I even improve that code.
And that's all because I want to shine in front of others when they review my pull request.
Some healthy peer pressure is great for producing good code quality.
Nobody wants to look like a fool in front of their teammates. If you know that your coworker will review your code, you will spend extra time and effort to make it perfect.
9) The Cost of Defects Is Lower the Earlier They Are Detected
Unfortunately, in practice, it is impossible to develop software without any defects—at least if you don't want to work with the overhead of a mathematical model, which can prove that the code is bug-free.
If software is deployed in production and the program contains a critical bug, then usually multiple people are involved in the process to provide a fix.
As an example, let me describe the process in my previous company for such situations:
First of all, the customer will notify support about the problem. Then the support team usually will try to reproduce the issue. If that's successful, they will notify the Product Owner, who will evaluate the priority of the bug. In case of a critical issue, he will inform the development team, who will start to work on the fix.
Meanwhile, probably other customers will report the same bug. In a company with established processes in place, the support team will make the incident publicly visible to notify existing customers about the ongoing issue upfront. Depending on the business and size of the company, the account manager might be contacted directly by customers and get involved in the process as well.
During the process of fixing the bug, the development team gives regular updates about the progress, which are reported within the company as well as updated on the public notifications. When the bug is finally fixed and deployed, the account managers or support team has to inform the customers about it.
As you see from this example, a lot of people are involved in the process to deal with a critical issue which made it to the production environment.
This results in high costs. First of all, you have the direct cost of the people involved in the process to deal with the issue. And second of all, probably even more important are the indirect costs: leaving customers, decreased reputation of the company, etc.
Therefore, it is obviously good practice to build multiple lines of defense to catch software defects as early as possible.
Usually this is done by different types of testing, like unit testing, integration testing, regression testing, or manual testing.
But often, companies miss the point that code reviews also act as a line of defense, because during a code review you can also catch bugs. As code reviews are done in a very early phase of the development pipeline, catching and fixing bugs is way cheaper than finding and fixing them in later stages of the development.
10) Mentoring Junior Developers
If you have a junior developer starting on your team, how can you help her to grow and improve?
Of course, you can give a presentation about a technology or a module. You can host a workshop, or you can give explanations on-the-go when she touches on a new subject as part of her task.
These are all things which are helpful and are necessary to a certain degree. But she needs regular feedback on the work she delivers, meaning the code she develops.
Code reviews are a great way to do that.
When code reviews are part of the development pipeline of the team, then this also feels natural for the whole team to help the junior grow and improve as a developer. This makes it a responsibility for the whole team—otherwise, the team usually expects the team leader to do all the work for training the junior.
As code is reviewed for every team member, it is also perceived from the junior as less intimidating, even though she might get a lot of comments to make changes before her pull request finally is approved.
Next to that, she also has to review code that has been produced by other developers.
Reading code and trying to understand what it is doing is a great way to improve your own coding skills.
And if this is part of the team development pipeline, this happens daily and feels like a natural part of your job.
Are There Any Downsides?
Ok, you’ve heard of the 10 benefits of code reviews. Now, you might ask: Are there any downsides?
Well, usually you hear the following arguments from people who do not see the value of code reviews:
A code review prolongs the development time of a feature because after the coding is finished, another person has to review the code before it can move to the next step in the development process.
In addition, the reviewer uses the limited and expensive time at work for a review, while he could be more productive and continue to code. Therefore, code reviews result in higher development costs.
These arguments are probably true on a very short term, but I am convinced that on a long-term basis code reviews definitely pay off: you get better code quality, improved knowledge sharing in the team, fewer bugs that need to be fixed, better teamwork, among other benefits.
How to Implement Code Reviews
If your team does not have code reviews in place yet, there are different ways that you can implement code reviews with your team. There are four types of code reviews:
- You can do an instant code review using pair programming.
- You can review each task synchronously after coding is finished.
- You can review each task asynchronously after coding is finished.
- A long time ago, I even used to have code review sessions together with the whole team in one room about once every month
I personally prefer the option to review each task asynchronously, which is basically the experience on GitHub: When the coding is finished, the coder creates a pull request. Sometime later, when the reviewer has time he will perform the code review asynchronously based on his own schedule.
In contrast, the synchronous code review happens immediately after the coding is finished. The reviewer stops with his current work and joins the coder at his desk to review the code together.
There are pros and cons for both the synchronous as well as asynchronous review method.
Get Started on Code Reviews
No matter which code review method you think is the best fit for your team, the important part is that you have code reviews in place as an integral part of your development process.
If you don't have them yet, then I encourage you to start a discussion with your team and explain them about the benefits of code reviews as you have just learned.
You don't need to convince the whole team at once. In the beginning, it is enough to convince only one of your colleagues and you can get started to review each others code. Over time, as your coding skills improve and you write more robust and clean code, other team members will get curious and eventually join in as well.
Alright, that's it for today. In case your team does not have code reviews in place yet, I hope you got some ideas on what you can do to get started. If you have any strong opinions about code reviews, please let me know in the comments.
Ok, stay tuned and take care.