NJL Heavy Industries

Technical Debt

2014-11-14

One of the hardest concepts for a programmer to convey to a non-programmer is the idea of of technical debt.

Technical debt is, fundamentally, the side-effect of a programmer's imperfect vision of a piece of software's trajectory.

Failure to see and understand a project's trajectory can come from many sources. A common one is changing business needs; maybe we plan on allowing multiple addresses for a user, but it turns out a user can only have one. The extra code in place to allow for multiple addresses is debt. It's code in our system that needs to be considered in future development and it doesn't add direct value. This lesson is encapsulated in YAGNI, "You Ain't Gonna Need It", which encourages us to not write any code just because we might need it.

Another common source of technical debt is lack of understanding of the actual problem being solved. No matter how clever we are, no matter how well we plan things out in advance, we're going to make mistakes. Somewhere between our idealized version and the real world, some special case we didn't consider, or interaction between third-party code, or something, is going to make things a little messy, or brittle, or not as clean as we would like it. There's no way of knowing what the code is going to be without writing the code, and writing code is a process of intellectual discovery. Surprises will happen. Sometimes they're good surprises! Often, they're bad ones.

Anything that's a special case, or messy, or untested, or hard to get a new programmer up to speed on, is technical debt. Your custom protocol that only takes half a day to understand? That's technical debt; use HTTP or something else off the shelf. Your crazy build process that only two people in the organization understand? That's technical debt. Automate that stuff. Your super clever code that does fancy math to figure something out? Probably technical debt; I bet the test coverage is atrocious, and code with fancy math probably needs better comments than you've got in it.

Technical debt is important because it is the thing slowing your development velocity. The fundamental limit on a programmer's capacity is how much can be shoved into their mind at once. This is why a low-distraction environment is important for programming. Technical debt adds to what you need to have in your head, without adding corresponding power.

As technologists, this is the case we need to take to business owners, and it's a hard one. When you're writing a list of features customers are screaming for on Post-Its, and arguing about order, it can be hard to try to force in, "set up an automated build system" or "refactor the user code to remove all the code about multiple addresses". These are costs that are hidden from business stakeholders.

It is our job, as technologists, to highlight the importance of adding tests, rewriting broken modules, refactoring, and improving infrastructure. At the same time, we need to admit to ourselves that it's usually in our nature to want to build grandiose frameworks and extensive tooling that's overwrought for the task at hand.

So we need to do two things. The first is we need to gain trust by focusing on removing technical debt from places where it really matters. If there's a service that's an absolute mess but doesn't need much work and meets business needs, we need to communicate that work on that service can be very minor tweaks or a near rewrite, with the middle ground being a painful mess. We then resist the urge to clean up that service "just because it needs it". We clean it up when it's not meeting business needs, and we get all stakeholders bought in on the idea that the service needs to be reimagined and recreated or left alone.

Second, we need to focus on infrastructure and debt removal that is directly useful to the task at hand. Planning infrastructure for ten times your current demand might be reasonable for a fast-growing startup. Planning infrastructure for a thousand times your current demand is a pipe dream that's going to take you down pathways that you don't need to explore.

Technical debt is very real, and has a material impact on a business. Technical debt and programmer quality are usually the only inputs that matter when it comes to innovation and meeting customers' demands on a product. Removing technical debt is important, but it needs to be motivated by a focus on how the debt in question directly affects the business.