About the author
Will Barrett is a Software Engineer, Technical Lead, and Engineering Manager from the San Francisco Bay Area with over 14 years of experience. He’s a Superset PMC Member of The Apache Software Foundation. He’s held staff software engineer and senior engineer roles at Change.org, Entelo, Sqwiggle and Preset.
Will is the author of On Learning to Program, a blog for new Software Engineers entering the industry. Will is also a certified reviewer on PullRequest where he’s caught hundreds of bugs, security issues, and other critical issues for over 40 teams.
Most technology companies really love efficiency, and the love for efficiency often begets a love for the concept of urgency - the idea that every task warrants fast progress. By instilling a sense of urgency in their employees, tech companies can drive greater productivity. This works to a point, but it can be quite hard on the code review process. Here are some tips for creating the space for review and revision in a high-urgency environment:
Define Levels of Urgency and the Expected Responses
By having a conversation about the different types of tasks that Engineering may come across with stakeholders it should be possible to define a set of urgency codes in the organization - this can be a numerical priority scale or simply “Emergency”, “High”, “Standard” and “Low”. Explaining that if the site is up and operating normally a change does not constitute an Emergency can help create breathing room for the Engineering team and allow the normal development process to be interrupted less frequently. The important component to make this work properly is to create objective measures that will define the urgency of a task. Generally most stakeholders will attempt to rate all requests at the “Emergency” level out of the gate, especially when their requests are competing for resources with requests from other stakeholders or departments. This can create an escalating urgency war. By creating a rubric with objective measures for the various priority levels and enforcing that rubric equally across the organization, Engineering can keep the balance.
Advocate for Quality
In high-urgency environments, quality will invariably suffer. Producing higher quality work takes more time and effort than producing low-quality work in the short term, but saves an enormous amount of time, headache, and re-work in the long term. As Engineers, advocating for quality can be one of our best ways to create the space we need to build sustainable systems. Here are some tips for doing this effectively:
Track the Number of Bugs Hitting Production
This is also known as the “regression rate” - by tracking the number of regressions per week or per deployment, the organization can understand how the quality of the code is directly affecting users. When this number is too high, it becomes clear that there is a quality problem at the organization. Quality problems can be addressed by leaning into practices known to reduce bugs, such as testing and code review.
Talk about the Project Management Triangle
Good, Fast, or Cheap - Pick Two (if you’re lucky).
It can be helpful to have conversations with leadership about where they want to lean. Do they want a quick and dirty test of a new idea? Well, maybe this project needs to be isolated from the rest of the system so that it can’t cause too much damage and everything will just get committed straight to the main branch. If “good” is anywhere in the conversation, then it becomes important to have solid software development practices as part of the plan, and this includes code review.
Recognize False Urgency
Many organizational stakeholders will apply pressure to complete their tasks as quickly as humanly possible. It is important to recognize when these requests are truly urgent - they are tied to a real deadline with consequences or every moment the request isn’t satisfied is causing harm to the organization - vs. times when the urgency is false. In the latter case, it becomes important to talk with the stakeholder, understand their reasons for putting pressure and reset expectations. The rubric described in the previous section can help with this in clear-cut cases but it’s important to understand the true motivations of stakeholders so that the rubric doesn’t become an organizational straight-jacket.
Create a Culture of Code Review
Engineers behave differently depending on the culture that surrounds them. In a culture of “everything needs to happen right now” it can be hard to do a good job reviewing code. The pressure to just LGTM everything from the business side can be high. As Engineers, it becomes our responsibility to create our own positive culture. Pursuing good quality checks and creating a practice of code review inside of the Engineering team can help balance out the business pressure and find a happy medium. Some ways to build this positive culture include praising thorough reviews, thanking teammates for finding problems in your work, and providing public recognition for the best reviewers at the organization. Though this can be a double-edged sword, as a manager it can help to track the reviews of the members of your team. While numbers here aren’t perfect, it can help to identify team members who could benefit from coaching on how to be a better reviewer.
When Things are Truly Urgent, Change the Code Review Approach
When the urgency is true urgency the code review approach needs to change. Rather than trying to improve the code submitted to meet the need I recommend only commenting on items that are truly dangerous. All other items can be treated as follow-ups. When things are truly urgent, taking on a small amount of technical debt to meet the need is usually worth it, and the technical debt can be addressed in the next pull request. A good way to indicate that this is happening is on the approval message. Here’s some example language:
LGTM. This is urgent and I think we should merge and deploy it as-is. I do see a few things that I’d like for us to improve in a follow-up PR. Once this is out the door I’ll comment on this with my recommendations and we can address them as a follow-up.
Don’t Forget to Follow Up on Incurred Technical Debt
Generally if an urgent request comes in that needs to be handled immediately as quickly as possible the solution will generate some level of technical debt. I generally like to deal with this technical debt in the same sprint if possible. The issues are fresh in everyone’s mind and it avoids a downward spiral as the code becomes less and less maintainable with each emergency. If this isn’t possible I create a ticket, assign it to the next sprint and we carve out space to handle it in the next planning session. This is important for two reasons: it keeps the team and the code running properly and it makes it clear to the business side of the house the true cost of properly responding to emergency changes.
Time pressure is a constant in most organizations. Balancing quality with speed is difficult for most teams. The Engineering organization tends to be the advocate for quality, with the business side the advocate for speed. The tools above have helped me navigate this discussion across multiple organizations as an IC and an Engineering Manager. I hope they help you as well!
Find this useful? Be sure to check out these additional articles by Will Barrett:
- How Giant Data Leaks Happen - Understanding Cryptographic Failures (OWASP Number 2 for 2021)
- What We Can Learn from the Ruby on Rails Project about Code Review
- 5 Ways I Provide Value as a PullRequest Reviewer When I Start Reviewing a New Project
- How to Catch the Top OWASP 2021 Security Category - Broken Access Control - in Code Review Part 1 and Part 2
- Tips for Migrating to a New Computer for Programmers
- The Top 5 Most Common Security Issues I Discover When Reviewing Code
- Reviewing One’s Own Code
- Handling Code Reviews with Empathy
- What We Can Learn About Code Review From the Apache Superset Project
- What We Can Learn About Code Review From the Apache Spark Project