Confidence Driven Engineering

There used to be a time, not too long ago, that I thought that opinionated engineers were a nightmare to work with. I still believe this, but as I've continued building software over the years, I, too, am starting to form some opinions on how things ought to be. I don't hold these ideas or principles over everyone's heads around me, but I do try to share them when I think it's appropriate.

One of these opinions that I've been increasingly building up in my mind is that every effort in modern software engineering around quality leads up to building confidence in a system, component, or script. All paths lead to the same destination: confidence.

Take for example: code coverage. Code coverage absolutists will enforce a 90+% coverage for all code in the codebase. A high code coverage percentage likely means the code is reliable and resistant to regression. If you cover 100% of your code, this means that changes to existing code will require the developer introducing the change to update something. This assurance reduces the probability of regressions.

However, one can achieve high code coverage in any number of ways. So even high code coverage won't save you from a bug that takes down production, but it certainly increases your confidence that it won't. You can write an incomplete test that doesn't test all expected inputs, but does cover all branches in the code. So 100% code coverage does not mean 100% confidence. Most of the time, engineering is about trade-offs. If we know achieving 100% code coverage, something not very easy and likely to be a result of shortcuts taken, does not lead to an equal amount of confidence being built, then we should make a trade-off for something that boosts the signal of confidence. Some of the best developers I know won't focus on code coverage alone or enforce a strict percentage value... within reason.

Furthermore, these efforts have a compounding effect on building confidence, or at the very least, the ease in which confidence is built. Code coverage is an example of this (explained earlier), but another really good one is having reliable Continuous Integration and Continuous Deployment (CICD). While code coverage can help you build confidence at the unit level (functions, classes, interfaces, etc.), CICD helps you build confidence at the integration or component level (infrastructure, third party dependencies, secrets, etc.). Once you have a reliable CICD that can signal when software is built up to spec (note: this relies on previous investments to build confidence), teams can move fast without breaking too many things.

Having reliable CICD also allows developers to control variables when building software, which increases confidence in different parts of a system. It provides an automated way to validate existing confidence-building measures. What is my confidence level for a junior developer on knowing that they should run a linter on their code? Not as high as trusting my automated system will do it.

In 2022, I don't think I need to spell out the benefits or properties of these best practices. My point is that these things ultimately build confidence. In the real world, you can't always have 100% code coverage, or you can't easily mock or run a dependency service for testing. When the cost of building these things outweigh their benefit, either because the ROI in confidence isn't high (what is the increase in confidence for going from 80% code coverage to 90%? 100%?) or the cost is too prohibitive at the moment, as engineers, you have to make a decision on the best ROI for building confidence. Expending time on code coverage may not lead to the best outcome for your team or product.

My final note on this is that confidence is subjective: confidence itself is a qualitative measurement. We tend to put a number to it, though: "I'm 50% confident that I can make that jump," but I'd argue that that's just human nature trying to quantify something. My 50% confidence is not the same as yours. Everyone has different comfort levels: risk-takers may be willing to make a favorable call based on 10% confidence, while the risk-averse may not. Whenever an engineer submits new code to be reviewed, and they've introduced a blind spot in confidence (a new integration, a new algorithm, a new infrastructure dependency), I always ask them: "how confident are you in this change?".

I don't like forcing my definition of confidence on others. In some cases, I have had to put my foot down and enforce some baseline of confidence, but I much prefer holding engineers accountable to their level of confidence, and, hopefully, after working together and agreeing on some common values (How We Work Together), the baseline for confidence is implicitly understood. If we focus on confidence, I believe that we can ship high quality software at a fast pace.