Of the Importance of Controlling Your Technical DebtWhere Aristotle’s Golden Mean is precious
In my not-so-long career, I’ve often been at odds with one of my directors about one topic: quality. We’re both of the mind that it’s a necessary thing in our projects but, basically, our perception of what’s “good enough” is different. Here are some thoughts.
More on My Case #
I think I’m not the only one, but I work in several steps. I iterate, very like the Agile approaches recommend. Fundamentally, the main steps are the following:
- Make something that works.
- Review and enhance the solution so that it’s “better.”
“Better” is always subjective. That particular director has known me for a while, and I suppose he thinks that, to me, it means “more beautiful, more abstract…” That’s why he always says, “‘Better’ is the enemy of ‘good,’” meaning that I’ll take time tweaking something that works, possibly breaking it, with no added value for the user.
I can’t say I blame him: in my youth, he may have been right about me. Today, though, when I’m in the step of making things “better,” I want to ensure the code will be maintainable in the future, and that involves everything that code writers are supposed to hate:
- Make sure the code is correct, remove obsolete code from proof of concept.
- Properly document and comment everything that may not be obvious at first reading1.
- Test everything that should be, with comments and documentation when required, too. That involves a focus on all requirements, functional as well as non-functional2.
It seems common sense. So, where does this divergence in our opinions come from?
Management Versus Technical Perspective #
When you’re a computer service company, you sell a project before it begins at an estimated price. The whole game is not to overprice it so that the client will trust you rather than the competition, nor to undersell it because realizing it will cost you. Once it has been sold, the second part of the game is to make sure that it costs is lower than the price you sold it, ensuring some profit.
So, when a young so-called technical expert tells you it works but he still needs to work on it, you think “Hell, I could give this to the client and have him happy, but I’ll lose some more money just because of an esthete. If it works, let’s call it a day!”
Then, if you’re a guy like me (the today me, a bit humbler than the young know-it-all at the time), you don’t perceive this additional work as wasted time, just as something that is expected. Making sure the code can be maintained is not a cost, it’s an investment on the future.
Let’s imagine that the same client comes back a few years later with some evolution requests.
If we went too fast the first time, adding those will be costly.
A disgruntled developer could even say that the people who wrote the code the first time did a mess of a work.
How frustrating for the client!
They spared no expense and all they got was this lousy
You may lose your image and your reputation of making quality quite quickly.
To sum up, my director focuses on delivering the product as ordered and in time, while I add to this the fact that people will have to work with it, debug it, make it evolve… In other words, he thinks about user experience now only while I think about both user experience now and developer experience in the future.
Here Comes the Technical Debt #
What’s technical debt? It’s something you refuse to do now to save some time. Basically, you know you should change it, but you have more urgent tasks, so you let it stay for now.
But interests build up: as the time passes, you add code and features based on your not-so-correct basis. Then, one day may come when you change it, either because you agreed to do it or because you must do it in order to allow for the next feature you need to add. What’s different is that, instead of changing only the incorrect origin, you also need to update everything that was built on it3.
That’s what controlling your technical debt is about: ensuring that, if I have to update my software in the future, I won’t have a big backlog to update before that.
Note that this quick post doesn’t even start to take into account the cost of fixing bugs related to the technical debt.
Don’t Go Over #
There are such things as over-quality, over-engineering. Those were what my director was afraid of.
To managers, I advise you make sure of whether your team tries to avoid technical debt or if they just want to go to far because it’d be “better.”
To the technicians, always keep in mind you’re not writing code for the beauty of it. You’re doing it to achieve a purpose, to serve a functionality. Don’t build an ultra-generic solution that will handle a single case, don’t implement a plugin manager for a process that is straightforward… Don’t build a whole power plant if your goal is to light a bulb. Those are another form of technical debt: code so complex that nobody will be comfortable maintaining it.
If you need something to be done because it’s a risk for the future, just explain that to your manager4.
Illustrating This #
Before parting, let’s go back to my usual image: you’re building a house. You can see that a pipe is not how you expect it to be, but you want to hurry and it’ll be “good enough” for now, as water still flows. “Good enough” when you have to deliver means you make as if it’s finished: you put the wall and tiles over your pipe.
One day, you’ll want to add another sink, or just fix the pipe you know is not correct. You first need to remove the tiles and plaster, change your pipe, and then put everything back. But maybe changing what’s in the wall forces you to change the wall itself, which in turn may have an impact on the framework…
That’s not taking into account all the leaks (bugs) you’ve had to put up with, in the meantime, just because the pipe wasn’t right in the first place.
There’s so much more to be said about quality and technical debt, but this post was supposed to be a short one. If the topic is of interest, we could go deeper in future posts. The message here is this: postponing the quality or denying the need for it is building up technical debt and its interests, which someone will have to pay someday.
I was once of the mind that code was its own documentation, but I now know that some natural language comment can go a long way in saving time understanding that code and even prevent from getting it wrong. ↩︎
Non-functional requirements are the criteria that can be used to judge the operation of the system rather than its behavior. For instance, “should respond in less than 500 ms” is a non-functional requirement. ↩︎
If you’re in this case, I hope you had everything properly tested. This’ll help you detecting possible regressions. ↩︎
In very rare occasions, they may be more politicians than project managers. In those cases, deploying new features might be more important to them than mitigating risks. Once, I warned about three big risks related to technical debt, my product owner said, “You’re right, but we need features right now.” A few weeks later, a critical incident came up on one of the risks I had highlighted. I was highly tempted to let everything burn. Fortunately, I remembered my teammates and impeded users, and was more constructive than this. ↩︎