Easy and Effective Code Reviews
Understanding and reviewing other people’s code can be challenging due to different coding styles, complexity, and lack of context. Code might be written in a way that is unfamiliar, or it might include complex logic that is challenging to decipher without in-depth knowledge of the project. However, mastering code reviews is essential for maintaining high-quality code, building team collaboration and having built in knowledge sharing.
Different Code Review Workflows
Most of the time, your team will use a combination of these workflows in your daily operations.
👥 Pair Programming
Two developers collaborate and continuously review each other's code. The more they collaborate throughout the coding process, the better.
- Key Benefit: Immediate feedback and knowledge sharing, leading to higher code quality and faster problem resolution.
👀 Over-the-Shoulder Reviews
A quick, informal review by another developer. Teams or Slack chat, or even coffee break conversations, are perfect for this.
- Key Benefit: Quick and efficient feedback without the need for formal processes, encouraging a collaborative environment.
🛠️ Tool-Assisted Reviews
Using platforms like GitHub, GitLab, or Bitbucket for structured reviews.
- Key Benefit: Structured and organized review process with built-in tools for tracking changes, comments, and approvals, enhancing collaboration and accountability.
High Level Benefits of Code Reviews
There are several great high level benefits to making regular code reviews a part of your team's workflow.
📈 Improve Code Quality
Catching Bugs and Potential Issues Early:
Code reviews provide an extra set of eyes on the code, increasing the chances of identifying mistakes that the original author might have overlooked.
This process helps catch logical errors, edge cases, and potential bugs before they make it to production.
Example: A bug in a payment processing module is identified and fixed before it causes financial discrepancies.
Additional Example: During a code review, a reviewer notices that a newly added API endpoint does not properly validate user input, preventing a potential security vulnerability.
Ensuring Proper Testing:
Reviews can ensure that adequate tests are written for new code, improving the overall test coverage and reliability of the codebase.
Reviewers can suggest additional test cases that the original author may not have considered.
Example: A reviewer suggests adding tests for edge cases in a function that calculates discounts, ensuring the function behaves correctly for all input values.
💡 Knowledge Sharing
Helping Team Members Learn from Each Other:
Code reviews are an excellent way for team members to share knowledge and best practices.
Junior developers can learn new techniques and approaches from more experienced team members, while senior developers can stay informed about new ideas and trends.
Example: A junior developer learns about advanced error handling techniques by reviewing a senior developer’s code.
Additional Example: A reviewer points out a more efficient algorithm for a text based search function, introducing the author to a new method they hadn’t considered.
Understanding Different Parts of the Codebase:
Regularly reviewing different parts of the codebase helps team members become more familiar with the entire system, reducing the bus factor.
🚍 Bus Factor: If a single person got hit by a bus. What level of impact would that have on the business or team.
This familiarity can be crucial when someone needs to step in to fix bugs or implement features in parts of the code they didn’t originally write.
Example: By reviewing a feature implemented in the database module, a developer becomes more familiar with the database library and can later contribute more effectively to related tasks.
🔂 Consistency
Ensuring Adherence to Coding Standards and Best Practices:
Consistent code is easier to read, understand, and maintain. Code reviews help enforce coding standards and best practices across the team.
This consistency includes following naming conventions, code formatting guidelines, and design patterns.
Example: A reviewer ensures that new code follows the team’s established pattern for handling configuration settings, making the configuration process predictable and reliable.
Additional Example: A developer suggests implementing quality control automation tools into the CI pipeline to ensure formatting and coding standards are met automatically. This frees up reviewers to focus on functionality rather than formatting.
Promoting Uniform Code Style:
Uniform code style helps reduce the cognitive load required to understand the code, as developers don’t need to adjust to different styles.
Code reviews ensure that everyone on the team adheres to the agreed-upon style guide.
Example: A reviewer points out inconsistent variable naming and suggests using the team’s standard naming conventions, improving readability.
💣 Reduced Technical Debt
Maintaining a Cleaner, More Maintainable Codebase:
Regular reviews help identify and address code that could become technical debt if left unchecked.
By catching issues early and refactoring as needed, the team can prevent the build up of problematic code that would be costly to fix later.
Example: Refactoring opportunities are identified and acted upon, preventing the buildup of legacy code that will be to costly to fix years later.
Additional Example: A reviewer suggests modularizing a large function into smaller, more manageable pieces, making the code easier to understand and maintain.
Proactive Refactoring:
Reviews provide opportunities to refactor and improve existing code as new features are added, ensuring the codebase remains healthy.
This proactive approach to code maintenance helps avoid significant rewrites and disruptions in the future.
Example: During a code review, a reviewer notices a recurring pattern in multiple files and suggests creating a shared utility function to reduce code duplication and improve maintainability.
Addressing Technical Debt Incrementally:
By incorporating refactoring and improvement suggestions into regular code reviews, the team can address technical debt incrementally, making it more manageable.
This approach helps maintain a balance between delivering new features and keeping the codebase clean and efficient.
Example: A reviewer identifies an outdated dependency and suggests updating it as part of the current changes, reducing the risk of security vulnerabilities and compatibility issues in future releases.
Low Level Benefits of Code Reviews
The low level benefits from doing code reviews really show why code reviews are critical to software development success.
🏎️ Frequent Reviews Keeps Things Moving
Use the different code review workflows for performing formal and informal code reviews. It keeps things moving and helps prevent refactors or tech debt.
When reviews happen quickly, developers aren’t stuck waiting for feedback. This keeps the project moving forward and maintains a steady pace.
It’s like a well-oiled machine – when one part is done, the next part can start right away.
Example: Imagine you’ve just finished a feature and submitted a pull request. A quick review means you can address feedback and get it merged fast, so you can dive into the next task without delay.
👀 Catch Problems Early
Spotting bugs and issues early on prevents bigger problems later. It’s easier and cheaper to fix things now than after everything is built on top of it.
Think of it like catching a small leak before it turns into a flood.
Example: A reviewer quickly notices that a new function could cause a performance issue. Fixing this early avoids headaches and ensures the app runs smoothly in production.
🔄 Quick Feedback, Quick Fixes
Fast feedback means you can make changes while everything is still fresh in your mind. This makes revisions more accurate and effective.
It’s like getting feedback on a draft while you still remember all the details, rather than trying to recall it all weeks later.
Example: You get feedback on your pull request within a few hours. You can make the necessary changes right away, ensuring the feature is ready on time.
🛠️ Use Tools to Stay on Track
Automated notifications can alert reviewers when new code is ready, so nothing slips through the cracks.
Setting aside dedicated review times can ensure that code reviews are prioritized and happen regularly.
Example: With GitHub notifications, team members get alerts when a new pull request is created. Plus, the team has a daily review time every morning to make sure reviews are done consistently. Or it can be used to review designs prior to a pull request.
🤝 Make It a Team Effort
Encourage everyone to understand the importance of timely reviews and actively participate. It’s about creating a supportive and collaborative environment.
Think of it as a team sport – when everyone knows the plays in order to reach the goal. It is a lot easy to score and win!
Example: The team adopts a practice where every developer reviews at least one pull request per day. This collective effort ensures quick reviews and helps everyone contribute to high code quality.
By focusing on timely code reviews and using tools and team practices to support them, you’ll keep the development process smooth, maintain high code quality, and foster a collaborative team spirit.
People Involved in a Code Review
👤 Author
The author is the developer who wrote the code. Their job is to explain the context and purpose of their changes, address any feedback, and make the necessary revisions.
👥 Reviewers
Reviewers are team members with relevant expertise, such as code owners, team leads, peers, or testers. They check the code for quality, functionality, readability, performance, and adherence to coding standards. Reviewers provide constructive feedback, suggest improvements, and ensure the code integrates well with the existing codebase.
Example: A typical approval process might require at least two reviewers to approve the changes before the code can be merged or deployed, along with all automated tests passing.
Having multiple reviewers with different perspectives makes for more thorough reviews. This not only helps catch various issues but also fosters a collaborative learning environment, improving overall code quality and teamwork.
Performing Effective Code Reviews
👟 Key Steps to Follow
📝 Prepare: Understand the context and changes made. If there is a feature description or ticket for the work, take time to read it carefully.
- Example: Before reviewing a new feature implementation, read the associated Jira ticket to understand the requirements and context.
❓ Ask Questions: Clarify any questions with the author. There is never a stupid question. Not asking questions can lead you down an incorrect path or misunderstandings.
- Example: If you're unsure why a specific approach was taken to solve a problem, ask the author for clarification to understand the reasoning and any constraints that influenced the decision.
🔍 Prioritize Issues: Focus on major concerns first. Don't get lost in minor details or preferred methods that may not be critical at this stage of development.
- Example: Fix a serious logic error that affects functionality before pointing out minor stylistic issues, like variable naming conventions.
💬 Provide Feedback: Offer constructive and actionable suggestions. Include examples and code snippets where possible to make your feedback more constructive and helpful.
- Example: Instead of just saying "optimize this query," suggest. "Consider using an indexed column to speed up the search, like this:
SELECT * FROM users WHERE indexed_column = 'value'
"
🎯 Key Focus Areas
✅ Functionality: Ensure the code meets its intended requirements. Verify all specified features and functionalities are implemented correctly. Check if the code handles expected inputs and produces correct outputs. Assess if the code is extensible for future changes.
✅ Simplicity: Make the code easy to understand and maintain. Avoid over-engineering; simpler solutions are more reliable and easier to debug. Follow the “Keep It Simple, Stupid” (KISS) principle. Ensure the code can be easily modified or extended without new bugs.
✅ Readability: Ensure the code is clear and understandable. Use meaningful variable and function names. Include function descriptions and comments for complex sections. Organize code logically, grouping related functions and classes.
✅ Performance: Check for efficient use of resources like memory and processing power. Identify and address potential bottlenecks or performance issues. Balance performance with simplicity and readability. Consider the code’s impact on overall system performance.
✅ Coding Standards: Adhere to established coding standards and best practices. Ensure consistent formatting, such as indentation and spacing. Follow naming conventions for variables, functions, and classes. Use appropriate design patterns and architectural principles.
✅ Error Handling: Properly manage exceptions and edge cases. Use language features and tools for error handling, like try-catch blocks and logging frameworks. Avoid custom error reporting unless necessary. Ensure error messages are clear and maintainable for future debugging.
🕳️ Common Code Review Pitfalls
🚫 Overloading Reviews: Reviewing too much code at once can cause important details to be missed. When faced with an overwhelming amount of code, it becomes challenging to maintain focus and identify critical issues. It is similar to trying to read an entire book in one sitting; you might overlook key plot points or details.
- Solution: Break down the review into manageable chunks, ensuring each part receives the attention it deserves. As well as making it easier to rollback certain parts if need too. Smaller commits are always better than one huge one.
🚫 Ignoring Context: Failing to consider the broader implications of changes can lead to integration issues. Code doesn’t exist in isolation; it interacts with other parts of the system. Ignoring the context can result in unforeseen problems when the code is deployed.
- Solution: Always take a step back and think about how the changes will impact the overall system. Ask questions like, “How does this fit into the bigger picture?” or “Are there any dependencies that might be affected?” or "How does this affect performance and scalability?"
🚫 Nitpicking: Focusing on minor, stylistic issues instead of significant concerns can be counterproductive. While consistency in coding style is important, it’s crucial not to get bogged down by minor stylistic preferences during a review. Nitpicking can slow down the process and frustrate the author.
- Solution: Prioritize significant issues that affect functionality, performance, or maintainability. Save minor stylistic suggestions for a separate discussion or a follow-up review.
Tool Assisted Reviews
Code reviews can take place in various environments, each offering unique benefits and tools to streamline the process.
🖥️ Code Hosting Platforms
GitHub: Offers a robust pull request system where reviewers can comment on specific lines of code, suggest changes, and approve or request changes before merging.
GitLab: Provides a comprehensive code review process integrated with its CI/CD pipelines, allowing for inline comments, discussions, and approvals.
Bitbucket: Features pull requests with inline comments, task management, and integration with Jira for tracking issues and progress.
Azure Repos: Part of Azure DevOps, it offers pull requests with advanced code review features, including policies, branch protection, and integration with Azure Pipelines.
💻 Integrated Development Environments (IDEs)
JetBrains IDEs (e.g., IntelliJ IDEA, PyCharm, DataGrip): These IDEs offer built-in code review tools that integrate with version control systems, allowing developers to review code changes directly within the IDE.
Visual Studio Code (VS Code): Through extensions like GitLens and GitHub Pull Requests, VS Code enables developers to review and comment on code changes without leaving the editor.
👕 One Size Does Not Fit All
The code review process should be flexible and adaptable to your team's unique needs. Consider the size of your team, the complexity of the project, and the deadlines involved. There is no perfect system, and tradeoffs are inevitable when choosing a workflow. Allow your process to evolve and adapt as your team's requirements change, ensuring it remains effective and efficient.
Bringing It All Together
To ensure effective code reviews, adopt a structured approach that emphasizes key aspects of code quality and fosters a collaborative environment. By following these best practices, your team can enhance the codebase and work more effectively. Integrate these practices into your daily workflow and focus on continuous improvement rather than perfection. Remember, code reviews are not just about finding bugs; they are an opportunity for learning and growing together as a team. Let us commit to these practices and elevate our code quality and teamwork.
For more details and a comprehensive understanding of these concepts, you can watch this great video from JetBrains.
Subscribe to my newsletter
Read articles from Derek Armstrong directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Derek Armstrong
Derek Armstrong
I share my thoughts on software development and systems engineering, along with practical soft skills and friendly advice. My goal is to inspire others, spark ideas, and discover new passions.