Relationships And Code Shipping
What really is important to get past code review? A lot has been said about good tooling, and good practices. This is a look at why I think we do it all in the first place, and how to get better.
Those of us in software engineering circles are familiar with what goes into the code release process — making small iterative changes, writing good descriptions, setting up Continuous Integration/Deployment pipelines, etc. These tasks, although sometimes tedious, direct changes and help code reviewers give timely feedback. They are all generally accepted practices, but my observation is that they are often viewed in isolation and in a binary way. For example, someone might say “a change description is missing” (opposite of which is a paragraph of text). Plus, the real driver for change is the feedback that humans give.
The way I see these specific practices is through a lense of human relationships.
The idea is simple: releasing a change is a function of two things:
The trust between the author and reviewer(s)
The author’s confidence in the ability to release safely to production
With less trust, it may appear to the author that the code reviewer is delaying or is overly picky. When there’s more trust, it's not about the change as much about whether it can be released safely with confidence.
Less confidence on the part of the author leads to more manual checks, suspicion, and uncertainty. When they’re more confident, it takes the pressure off from finding all the problems early.
Reframing it like this gives us an opportunity to think about the problem not in terms of whether "you wrote a good Pull Request description" or "we have a linter for this" but in terms of relationships and what can be done to influence trust and confidence.
Building Trust
First, it is unlikely that there is absolutely zero trust between any code reviewer and their change author. It’s difficult to fathom how any such work relationship can function with a complete lack of trust. Therefore, the trust dynamic is relative and dependent on the changes and the personality and quirks of each reviewer. Trust is like a bank account, where each small token of trust is debited and from time to time, credit must be taken too. The balance is fluid and always relative to the current level of trust in the relationship.
Here’s what I consider to be the most important things code authors can do to build trust with reviewers:
Cover the context of the change in sufficient detail in the description. Always include the current state and why the change is needed.
Provide a test plan. Some changes may not have automated tests. Showing proof (e.g., a screenshot) that the change works helps to build trust.
Outline any potential impact to latency, throughput, cost, downstream users and services, etc.
Detail failure scenarios and how to recover from them should they occur.
Ensure the code is simple and readable. If you just finished it and it works, do another pass with an eye on simplifying and restructuring it.
Learn the idiosyncrasies of your reviewers. Some focus on code clarity, some on general design. Review feedback is not a hurdle to get over with and forget but an opportunity to learn and remember something useful to employ next time.
Discuss the change ahead of time to ensure the context and the problem it is solving is clear.
Pair or mob on the solution together so that those small, architectural details are addressed before the review even starts.
There’s no need to do all of them every time - it would be counter productive. But it does mean that you can narrow down to just the things that build trust in your particular situation, e.g. maybe detailing failure scenarios and how to recover from them is more important than impact on latency. Corollary, if most of these practices are missing most of the time - eventually it chips into the trust credit.
Trust can also be explicit by exhibiting the above mentioned behaviours, but it can also be intrinsically acquired. Say, if you are a recently hired senior engineer, the assumption is that you will be showing some of those behaviours consistently. As a result, trust building happens quickly; experience gives you an upper hand. On the contrary, if you’re just starting out, it may take a couple of rounds of feedback before you make it a habit.
Building Confidence
Like with trust, it's unlikely that there's a complete absence of confidence on the behalf of the author. Their level of confidence is also relative to the change that’s taking place and depends on a multitude of factors.
Here are what I believe to be important components that can influence an author’s confidence:
Automation can go a long way. A playbook with manually executed steps works, but full automation Continuous Testing/Integration/Deployment and the ability to backwards deploy/recover easily in the case of errors instils confidence.
Keep metrics, logs, and alerts. Not all problems manifest early on. Observability gives others confidence that if a problem arises, it will be noticed early and the relevant people will be alerted.
Make documentation accessible. Ask yourself: If the change author is not around, would someone be able to recover a failure by just following the documentation?
Name the failure surface. Cyber security has a concept of the 'attack surface,' or the sum of all potential dependencies that could allow an attacker to gain entry to your system. Explicitly naming the failure surface can help evaluate the risk of the change and gain a confidence boost.
Small changes inspire confidence. Breaking down a change into small logical steps is a skill that not everyone possesses, but it is learnable. Making changes progressively over multiple stages allows the author to build confidence and reduce the risk of failure.
Know your tools. Chances are you'll feel less confident in a new environment with new tools and new systems and more confident if it's not your first rodeo.
If confidence in the release process is low, consider adding that extra paragraph about a test plan or an impact and rollback strategy. Or, consider investing in release documentation, automation, or improving familiarity. Taking the extra effort early can go a long way in building confidence for when more complex work has to be done later.
Putting It Together
Personally, as a code author myself, I always optimise for trust first. If I join a new company, work on an unfamiliar repository, or take on unfamiliar tooling, I put a lot of effort into explaining the context of the change and what testing I have done. Sometimes, in these scenarios, I will make a bare-bones change with empty functions in an effort to blow past the obvious “he’s new here” and turn the relationship into a more trusting version where the code reviewer understands my intention and is focused on solving the problem together.
As I get more comfortable with the trust in our relationship and listen to the reviewer feedback, I also sometimes think about how I could anticipate feedback earlier next time. This gives me (and my colleagues) trust that next time we will jump past minutiae details and discuss the solution immediately.
Ultimately, getting code released is not some obstacle course to please tools or reviewers. The end goal isn’t just to get past the finish line of getting the code to production and then move on. Release is just the first part of a three-part story: develop, maintain, deprecate. The story is written with human-to-human interactions, and the result depends on their relationship.
To have a successful relationship requires building trust and confidence. Both can be influenced through multitude of ways to ensure a successful outcome. At the end of the day, someone has to give feedback and trust it’ll be received, and someone has to confidently press that 'merge' button and release the change.
Great first post. This really resonates with teaching lesson planning to beginner teachers and more experienced teachers alike, especially these two points:
- Make documentation accessible. Ask yourself: If the change author is not around, would someone be able to recover a failure by just following the documentation?
- Small changes inspire confidence. Breaking down a change into small logical steps is a skill that not everyone possesses, but it is learnable. Making changes progressively over multiple stages allows the author to build confidence and reduce the risk of failure.
Look forward to the next installment!