Code: Our Biggest Sunk Cost

I’ve been enamored with writing code since I was nine years old. I still view it as somewhat like sci-fi: we type on our keyboards, and things happen. However, we are prone to committing a mistake here and treat code not as a means to an end but an end. I posit that we become more effective when we disconnected our self-worth from the amount of code written.

The dissonance often stems from the fact that code seems like the easiest way to assess the health of your organization. What other indicators can you easily track to judge whether things are on track? Measurement can be highly effective for improving your team’s processes and spotting bottlenecks. Nevertheless, if you put too much focus on things like the time it takes to review a pull request, you might skew your people’s ability to assess what actually matters.

Yes, it’s hard to become less dependent on code as a signal of worth and value. We’ve invested whole careers in becoming better at producing it. We look at all the code we’ve created with pride. However, the truth is that a large portion of the code written ends up merely being a sunk cost—and a sizable one. Consider the following suggestions, do they make you cringe? If so, you and your team are probably too invested in your code.

Have a Low Tolerance for Bugs

It is a given that no code is perfect, and there will be bugs and mistakes. Unless you’re working on life-critical systems, there’s no reason to try and minimize bugs to nothing. Still, in the same of “move fast and break things,” some teams allow too many bugs and not enough thinking.

When we don’t have a pressing need to churn out features, teams naturally spend more time assessing their steps. This is the “measure twice, cut once” aspect of software engineering. In theory, software is easy to change, and we can iterate on it. In practice, it is extremely rare to entirely scratch an approach after investing some time in developing it (there’s that sunk cost again). That is why some more planning can be beneficial. Working slower can result in faster results.

Delete Freely

See, if working slower means valuing thought over churning out code, deleting old code means that we value our precious and limited time more than maintaining useless features. In The Tech Executive Operating System I covered the topic of Meta-Reviews, partly for this kind of feedback loop.

When we retrospect work done, we don’t just consider how well we did the work—we should also give thought to whether that work, even if flawless, achieved the results we were after. Having to write features that we are not certain will move the needle is part of the job for many startups. Nevertheless, if we let these low-value features accrue, we will eventually have to pay the price for maintaining them.

Deleting code is sometimes more valuable than writing new code. It reduces overhead, makes space for innovation, and ensures that the system doesn’t become overly complex. No matter how splendid of a job your team did writing that feature, it has no reason to be there if it doesn’t move the needle. The sunk cost is sunk, but future maintenance can still be prevented.

Don’t Write It

A big part of creating engineering excellence is helping teams realize where they shouldn’t be spending their efforts in the first place. When I talk about creating product engineers, as opposed to principal engineers, this is a helpful test: Would you rather spend time coding a feature that can be done in another way, merely because it would make the team feel better?

While it might make sense to allow the team to have fun from time to time, the guiding principle should be delivering value. Teams that gets sucked into tech for tech’s sake often complexity solutions in the name of vague excellence and craftsmanship. Nowadays, it is becoming more and more frequent that we can deliver some of the impact without having to write any code. Integrating a third-party solution or using low-code/no-code tools can be an effective force multiplier.

Don’t put perfect code on a pedestal. It is a means to an end, not an end in and of itself.