Technical debt is the term used for the consequences of not tidying up software as it’s built.
Generally the result of taking shortcuts – of bodging things “for now” – technical debt is a way of describing the accumulation of all the technical mistakes that have been made over time. We all have to take shortcuts sometimes but if these aren’t then addressed at some point they can become a huge problem later, as we will see.
Technical debt can usually be described in terms of antipatterns and can also be caused by design decisions; architecture that won’t scale, a database that is hard to search, and so forth.
If you’re a coder, you’ll already know the impact of technical debt. If you don’t code, I’ll try to draw a picture of it for you.
Imagine you’re a builder. You’ve been asked to build a new bathroom in a house. You have all the tools and parts, you’re ready to go, you can SEE the bathroom in your mind, but you don’t have as much time to do it as you think you need.
Now imagine that the house is built on loose, sandy soil. The walls are not firmly founded; they’re shored up with angled beams. The plumbing just leads to a pit in the ground. The roof doesn’t fully cover the house and the rain gets in. The electrics periodically cut out so there is a generator in the yard that backs it up. Every so often, a wall falls down and someone runs over and pushes it back up again and tapes it back on.Everything inside you tells you to stop work on the bathroom and fix the foundations first of all.
But somebody is shouting at you to get the bathroom finished.
This is what working with technical debt can feel like.
You report that you need to stop working on features and fix the underlying problems but it falls on deaf ears, which hurts your sense of craftsmanship.
You feel like people think you’re a lousy builder who simply can’t build fast enough, which hurts your confidence.
It happens gradually, but eventually you can barely stand to come in to work in the morning.
A lot of good coders leave jobs at companies that don’t address the issue of technical debt. They can simply no longer bear working on projects that have achieved this kind of “critical mass”.
Existing in most projects to an extent, here are three distinct options to deal with technical debt, from least to most invasive.
This is where technical debt is simply accepted as part of a system.
If it’s not too bad and the system is still workable you might be able to carry on, accepting that the system is, like most things in the world, not ideal. I’d go for this option if a system is in maintenance mode and no longer has new features developed for it – for example, a product that is feature-complete but that may still require occasional bugfixes and security patches.
Unless significant feature development is going into a product, it may not be worth trying to “fix” it.
Refactoring is improving the design of existing code without changing its functionality. Remember, we’re not necessarily talking about bugs here, but making the code easier to work with. This is the preferred option in most cases as it doesn’t throw things away. It is, however, time-consuming. Myself, I refactor as part of my Test Driven Development (TDD) workflow and I recommend that refactoring be done as you go along (like in a good kitchen where the utensils are cleaned as you go, so a massive pile of washing up doesn’t accrue).
For this to work, it is important that managers and product owners acknowledge that refactoring is a vital phase of coding.
If a system isn’t designed well, it might actually be largely untestable and, you should NEVER REFACTOR WITHOUT TESTS!
If the architecture is bad, and the whole system is bad, then no amount of chipping away can rescue it. This is when a rewrite should be countenanced; only then should you effectively throw out functioning code.
This is the most invasive approach. From a commercial standpoint, it might not even be considered as an option. If that’s the case, though, the business runs a high risk of haemorrhaging developers for the reasons we discussed earlier. Sometimes, the plug has to be pulled on a system and failure to do so will only prolong the pain – you may sacrifice morale, opportunity cost and even your best engineers as a result.
As with most things, prevention is better than cure. There are many technical and process-based measures that can be taken to reduce the risk of accumulating technical debt and, furthermore, refactoring should be part of any Test Driven Development work loop.
It’s not just a technical issue, however. Managers need to work with coders to understand what the extent and ramifications of technical debt are on each project. In turn, coders need to clearly and professionally communicate what debt is being accumulated and how to effectively triage it.
When taking on a new project with existing code, it is vital that analysis be carried out to determine the level of technical debt already in place and create a plan to deal with it. Otherwise, you can end up lumbered with an unmaintainable mess!
I hope that this post has given a useful insight into what coders go through when dealing with large amounts of technical debt. This debt can cause a business to miss opportunities, suffer from poor morale, and even lose staff. It’s not all doom and gloom though – learning about why technical debt has built up enables you to put appropriate measures in place to manage it.
To learn more about how you can uncover the levels of technical debt present in your systems, visit the Code Review section of our site, and email firstname.lastname@example.org to request a product sheet with further details.