Some engineers believe they have to go to great lengths to eliminate every single piece of technical debt in their codebase. This focus on perfection ignores the cost of fixing debt, the risk of introducing new bugs and contagion (the chances of debt spreading).
As is with real-life decisions; not everything is black and white; there are a few grey areas. And experienced engineers are always making judgement calls.
That time I needed to borrow
A long time ago I was in a fix: I needed to make two huge capital expenses simultaneously: my first car and an expensive trip abroad. Alas, I only had liquid funds to cover about 75% of the total capital outlay required.
I initiated a sale of some of my non-liquid assets to raise the balance but I needed to make quick payments before the sale went through. Ultimately I had no choice but to borrow until the sale finalized.
You might be forced to borrow
Ideally, I wouldn’t have borrowed the money but I had a valid pressing need. Similarly, sometimes software projects have to borrow from the bank of technical debt. This is fine provided you immediately pay off the debt as soon as possible.
But not all nits need to be fixed. I used to be quite fastidious about small issues in code but over time, I have come to realize that not everything niggle has to be refactored.
To refactor or not to refactor: that is the question
I recently had to fix a minor issue in some old codebase, a benign exception was causing errors to be logged in our pipeline. These red-herring errors, which required investigations, had become a drain on our on-call engineers.
After fixing the nit; I looked around the code and wanted to make more changes. The code was bloated, relied on a few deprecated libraries and could be refactored. However, the 1-year-old codebase was extremely stable, used by every single code path and worked reliably all the time.
Thus, it came down to a Pro/Con evaluation.
- Cleaner code
- Maybe a small performance gain
- The possibility of breaking the entire product completely coupled with a slow turn-around time since this is a shared library.
- Expensive follow-up work to adopt the new version (new interfaces, new signatures etc.)
- Little or no extra code benefit to customers
The risks outweighed the benefits significantly. Moreover, since that code base wasn’t in active development; there was little chance of the bloat spreading around. Consequently, I shelved my cosmetic refactoring plans: those hours could be spent more effectively on higher-impact bugs/issues.
Before you fix that nit; consider the following:
- Return on Investment
You might also enjoy this excellent article: A Taxonomy of Tech Debt