Technical debt is the entropy and clutter in your codebase. It increases as developers add new code or modify existing programs, and it means that future developers will have more trouble wrangling the codebase. When technical debt reaches a certain point, the code begins to “smell.”
Any “code smell” is a good indication that something is deeply wrong with an app’s fundamentals. For example, classes that grow too large, or do too little, have pretty strong “smells.” Also stinky: Too many parameters, excessively long identifiers, and huge lines of code that are just plain scary to look at.
Nobody wants fundamental issues with their code. But erasing technical debt is often a laborious process that forces developers to put other initiatives on hold. Nonetheless, let’s show why tackling technical debt as early and often as possible is an unmitigated good thing.
Bugs Take Longer to Fix
Even simple bugs can take far longer to resolve if you need to pick your way through massive amounts of messy code written by multiple developers. Similar problems arise when attempting to introduce new features, even relatively small ones: technical debt can turn a relatively straightforward process into an impossibly convoluted one.
You’re Forced to Re-Do, Instead of Re-Write
With too much technical debt, rewriting a section of code becomes a massive chore. In fact, it might force developers to redo code from scratch, rather than tweak—and that can consume considerable time and resources.
I’ve seen this scenario happen twice. The first case involved a Delphi application for financial calculations; it was CPU-bound, and the way it was written meant it was impossible to multi-thread without a big rewrite. It ran on my 6-core 97 5930K (with hyperthreading), which meant that each core effectively doubled up. The net result was that the app could never exceed a maximum of 8 percent (i.e., roughly 1/12th of the available processing power). The part of the design that prevented multi-threading wrapped up many low-level calculations in a dll.
The other application existed before SQL databases were widely available. It was modernized for an SQL database—while still running as a hierarchical database “under the hood.” With over a million tangled lines of code, rewriting it would have been a very expensive operation. Thanks to excessive technical debt, it was simply never modernized.
You Defer to Tough Code
Sometimes, deadline pressure means it’s easier to put in a quick fix and defer the tough coding to a later time. This deferment is often due to technical debt, and it only leads to more technical debt.
Rather than implement functions fully when you write code, you think you can hardcode them to return a result, and then come back later to flesh them out. But sometimes you don’t come back.
It Lengthens Production Time
Technical debt is like credit card debt: Keep it small, and you can manage it. But once you miss those payments, things can spiral out of control, and it just takes longer to add new features or bug fixes.
I had that situation once with a product: Halfway through the lifecycle to an alpha release, management asked me to structure the app so it could work in a second language: Spanish. I already had a lot of English text hardcoded into the source code. Stupidly, I decided that I didn’t want to retrofit the Spanish text halfway through, so I got everything to an alpha version and then added the translated text in.
On later reflection, I made life a bit tougher on myself by continuing with the English-only version. Once I made the coding changes to support both languages, it was easier to add new dialogues and strings as dual languages.
Smelly Code Accumulates Fast
Here’s a popular example of smelly code: several functions with similar parameters. Large chunks of code (say, functions that stretch on forever when printed) are another strong smell. Sometimes you have an application where most of the functionality occurs in one class (i.e., its names contain things like Drivers, Managers, Systems, and Subsystems); that’s smelly, too. If you’re scanning your code and catching multiple “smells,” that’s a huge sign that technical debt is totally out of control.
Technical debt is inevitable unless you take great care. Even the smallest applications can accumulate debt if growth is not managed carefully. Here are some tried and true ways to reduce it:
• When you find a bug, add a test to detect it.
• Put “pay down technical debt” in your development plan. Don’t expect to reduce technical debt without allocating time to work on it. Such a thing cannot be done.
• Use static analyzers when possible. These will often give you a clue as to where smelly code is located.
While these steps may sound a bit intimidating at the start of a project, they’re well worth it in the long run. The alternative is a codebase that can slip very quickly out of your control.