Building Better Code: How to Conduct Meaningful Code Reviews

As a software developer, the importance of code reviews cannot be overstated. These reviews allow team members to scrutinize changes made to a project, helping to spot potential issues, suggest improvements, and ensure that the code aligns with project standards. In this post, I will delve into offering clear and constructive code reviews. If you haven’t already, please read my previous post, Before the Review: Strategies for Preparing Your Code, for an overview of how to approach the review process as the author.
Before embarking on a code review, it is crucial to remember that feedback should always remain objective. Reviews are not a competition, and unkind feedback helps no one. If the person submitting the code seems to lack knowledge in some areas, consider providing more specific feedback or mentoring them through another channel. This attitude fosters communication and collaboration, creating a more cohesive and enjoyable working environment.

Code reviews can be thought of in multiple phases or layers. First, preparing for the code review is essential. Ensure that you can commit to the review and give it your full attention, as this is a crucial step in the quality assurance process. I prefer to do this when I don’t have upcoming meetings, won’t feel rushed, and can focus strictly on the review itself. It is also helpful to avoid distractions from messaging platforms and emails until the review is complete. Understanding the context and acceptance criteria, the scope of the specific code you are reviewing, and setting up your environment are crucial. With the basics in hand, you can then check for readability and adherence to style guidelines. Once I’ve verified all the basics, I read through the code one more time, looking for functionality, structure, design, performance, and security issues. At each step of the process, I document my findings so that the person who submitted the code for review can understand my feedback. Use comments to ask clarifying questions about unclear code and suggest potential improvements. Ensure that your questions and comments are clear and concise. Use examples where possible and suggest alternative code improvements, along with reasons for the requested changes.

When starting a code review, it is important to first familiarize yourself with the documentation: the ticket description, acceptance criteria, and the pull request documentation. This will give you a high-level overview of the problem being solved, the developer’s strategy, and allow you to ask any questions you need before diving into your review. As emphasized in my last article, this is a great place for the author to explain their changes and thought process.
After reviewing the documentation, I like to read the changes as a diff. This lets me know what files were changed, gives me a chance to verify that all newly created files should be included, and provides a rough understanding of the changes. In GitHub, you can simply append “.diff” to the end of a pull request URL to see a diff with some context around the change. In this step, I focus less on the code as a whole and its interaction with the codebase and more on additions. You can also take this time to verify readability and style. Ensure that variable, class, and function names match the project style. Confirm that file names are correct and that files were added in the proper location. Verify that additional classes, methods, and functions perform the tasks suggested by their names. Document each finding as you discover it. If you are using GitHub, you can simply add a note on each problematic line. You can also edit comments later if you find an error in the same line that you did not document in your prior pass.

As you are looking at the diff, it also helps to have an editor open with the branch active so you can jump from file to file. On my second and final pass, I evaluate for performance, security, and the overall code quality within the project itself. Document your findings as you go.
When adding comments, it is important to explain why you are requesting the changes. If you are suggesting rewrites, while you do not have to fully write the change yourself, it can be helpful to show an example so that the author is clear about the requested changes.

Effective preparation for a code review reflects your dedication to both the project’s success and your professional relationships. By approaching each review with thoroughness, you demonstrate respect for your colleagues’ time and contribute positively to the environment. This approach builds a foundation of respect and collaboration that benefits the entire team while ensuring code quality for the project.

I encourage you to implement these strategies in your next code review. By fostering a collaborative and supportive environment, you can help your team grow and produce high-quality software. Share your experiences and tips on effective code reviews in the comments below. Let’s learn from each other and continue improving our review processes together.

Stable and Predictable Python Environments with Version Pinning

Managing Python Dependencies in Your Projects

Managing Python dependencies can be challenging, especially when transitioning projects between different environments or ensuring that all team members are using the same package versions. A common tool for managing these dependencies is a requirements.txt file, which lists the necessary packages for a project. However, often this file does not specify exact package versions, leading to inconsistencies and challenging errors across various setups.

Specifying package versions is crucial to prevent unexpected changes across different environments, whether among team members, testing setups, or production systems. In a recent Django project, my requirements.txt file listed all packages but omitted their versions. Each time I fixed bugs or added features, a new Docker image was built, always pulling the latest package versions. This approach was problematic as it could introduce untested changes to the environment.

A common method to pin packages involves installing the required packages via pip, followed by running pip freeze to list all installed packages and their versions. I found this method unwieldy because it mixed direct dependencies with transitive ones, complicating the removal process when updating the requirements.txt. To streamline this, I developed a Bash script that compares the output of pip freeze to the entries in requirements.txt, focusing only on the directly used packages and not including all dependencies.

To tackle this problem, we can deploy a Bash script that pins the versions of currently installed packages to match those specified in requirements.txt. This strategy guarantees that you and your team maintain a consistent environment, accurately reflecting the setup used during development. Below, I will provide a detailed Bash script and demonstrate how it can be seamlessly integrated into your project.

Continue reading