Essentially, a code review is when someone, most likely another person on a team or project, looks at the code you wrote for a specific feature and checks it for consistency, errors, styling, and more. Sometimes the person reviewing the code will also test the code locally in their own development environment to ensure all the requirements are met. I think that for any non-trivial code changes the reviewer should at the very least do basic testing of the feature to ensure that nothing was missed by the original developer. You would be surprised how often I review code that doesn’t even work. I actually think this step is so important, that the very first thing I do when reviewing code is download the code and test it based on the exact requirements of the feature. I do this before I even look at any of the code, because I want to test everything as if I was a user since that is how people will use the feature. If I look at the code before doing my testing then I will be biased since I know how the code works and may use the feature only in the exact way the code intends the feature to work.
You may think that this test is useless if you are reviewing your own code, since you wrote the code and have tested it many times, but it is very easy to get lost in writing code and forget to implement the feature exactly as it is specified. By reviewing my own code, I force myself to re-read what the feature should do and test my code on exactly the specifications of the feature. I generally find it best to do this review of your own code at least one day after you wrote the code. This removes most of the bias I talked about in the last paragraph and makes your testing more focused on how the user will use the feature.
Now after I have finished testing the code, the next thing to do is start looking at the actual code. This is where many people dive right in and start making comments on things to change, but I caution against this. Instead the best thing to do is first read all the code from beginning to end. You want to ensure you have a solid understanding of what the code is doing. This doesn’t have to be a perfect understanding, but you should have a general idea of what is happening in the code. Difficult to understand code is the quickest way to build a code base that is painful to work in and difficult to add to, so fixing confusing code should be a top priority. If you truly have no idea what is going on in the code, leave a comment saying so, but if the code is just confusing then try to leave a suggestion on how to clean up the code and make it more understandable.
After reading all the code and leaving comments on difficult to understand code, it is now time to start reviewing the code for correctness. This involves two steps. The first step is reading the code and checking for business logic errors or code mistakes. This could be something as simple as forgetting to check for null when an object could be null, or a more complex business mistake like accidentally comparing emails using case sensitive comparisons. The second step is re-testing the application manually, but specifically testing for the edge cases.
Most people that do code reviews stop here, but they are missing the most important step of any code review which is code quality. After checking to ensure the code works properly and is easy to read, the next thing that needs to be checked for is the quality of the code. One easy thing to check for is whether or not the core business logic of the feature is covered by automated tests. If at the very minimum the most important business logic of a feature is not tested then you need to leave comments suggesting which parts of the code you feel should be tested. Automated testing is one of the most important ways to ensure an application is working properly, so making sure to check for good test coverage in code reviews is incredibly important.
After checking to ensure test coverage is adequate, the next thing to check for is the structure of the code. When many people think of code structure they think of tabs vs spaces, how much indentation to use, how long a line of code should be, etc., but these things should all be taken care of by a linter.
Reviewing code structure is all about the overall architecture of the code itself. There is some overlap between reviewing the code structure and reviewing the complexity of the code, but in general code complexity is reviewed on a smaller scale, and code structure is the overall large scale of the entire project. This is the hardest thing to check when reviewing code since it is difficult to predict how the current code structure will impact future features.
And with that final step you have successfully completed a quality code review. To recap, the first step is to test the feature. After the feature is completely tested then you want to read all the code changes to gain an understanding of the code and check for any overly complex code. Next comes the validation portion of code review where you check the code for errors and incorrect business logic. Lastly, you want to review the code structure and quality to ensure the new code does not make the overall code base more difficult to work with.