Did it happen to you that your software developers went with “good enough” instead of polishing the code to perfection? If yes, you’ve most probably encountered technical debt which is a rather frequent occurrence in the software development world. In this article, we explain the meaning behind technical debt and provide insights on how to avoid and mitigate it.
The definition of technical debt
Technical debt is exactly what we mentioned in the intro: it’s going with “good enough” code instead of writing flawless code and fixing all bugs. Thus, we can define technical debt as the cost of additional work that arises from ignoring the pending fixes for the sake of quicker production.
Take two options as an example. Option 1 is writing messier code but achieving goals faster. Option 2 is spending more time on the code and necessary fixes and hence, moving at a slower pace in terms of development. If you select Option 1, the existing bugs and mistakes are here to stay - and they will pile up on a rolling basis. Note that technical debt is present mostly in Agile as the waterfall methodology simply excludes the possibility of it happening.
Now, you might be asking: why would anyone intentionally enroll in technical debt? Before looking into reasons, let’s first see the two types of technical debt: deliberate and inadvertent.
Deliberate technical debt
Deliberate technical debt means that you enrolled in technical debt intentionally and understanding the consequences. There are two types of deliberate technical debt:
- Reckless: when there is bad software architecture and the team believes you do not have enough time to polish the product as you need to ship it ASAP.
- Prudent: when you realize that the debt will be quite small and manageable and won’t severely affect the project.
With deliberate technical debt, you are aware that your code is not perfect and that you will have mistakes on the way but you allow it due to the abovementioned reasons.
Inadvertent technical debt
As the name implies, inadvertent technical debt is unintentional which means you did not suspect it until it happened. Same as with deliberate, there are two (same) types of inadvertent technical debt:
- Reckless: when the development team does not have enough knowledge of Agile practices and this lack of knowledge leads to poor planning and mistakes.
- Prudent: when the team understands what could have been done better after delivering the feature. In this case, the team was not prepared for technical debt but acknowledges it afterward.
Reasons for technical debt
Whether intentional or not, technical debt usually happens because of a certain reason (or several reasons) that are basically the same for any development team and any software project.
Need for faster time to market
The most common reason for technical debt is the hurry to push the product into the market as soon as possible. We won’t investigate the reasons behind such a hurry but one thing is clear: if hurried and pushed, the dev team will focus on speed instead of quality and won’t be able to pay attention to bugs and their fixes.
In my experience, the most common reason for technical debt is too much hurry that is often fueled by tight deadlines. If I were to work on a project with massive TD, I’d choose one of two options: If possible, eliminate the debt in a step-by-step manner (by separating it into smaller chunks) Do huge refactoring - basically rewrite everything from scratch.
Roman, Head of .NET at SoftTeco
Lack of experience and skills
Another common reason is simply lack of needed experience and skills as well as lack of understanding of Agile practices. All that leads to poor planning, delays, bugs, and errors. Developers simply don’t know how to approach the problem or do not even notice it, thus leaving the issues hanging behind. As a result, all these bugs pile up but nobody knows how to handle them.
Going over the established WIP limits
“Work in progress” limits usually define the amount of work that can exist in different stages of the workflow. WIP is usually used in Kanban board columns. WIP helps managers and developers see what has to be done and when it has to be done and the workload is distributed in a way to achieve maximum efficiency. But if WIP limits are exceeded for some reason, it will ruin the defined plans and will lead to confusion about the tasks’ priority and urgency of delivery. In this case, the team will sacrifice quality for quantity and speed.
Rapid growth velocity
It may also happen that your project is growing at an unmanageable rate and demands more and more new features. In this case, it becomes really hard for the development team to keep an eye on existing issues and their fixes as the team tries to implement new features simultaneously.
The most common TD reasons that I can think of are poor or no testing at all, working in a constant “startup” mode (meaning, the quality is “good enough for release”), poorly written code. Sometimes, technical debt is part of a strategy: a client may decide to leave it in order not to spend too many resources and time on making the product perfect
Alex, Android developer at SoftTeco
“Symptoms” of a technical debt
Now that you know the reasons for technical debt, it’s time to look into its “symptoms” or indicators that warn about a problem. These indicators are usually common for the majority of projects and are highly visible to anyone working on the project.
Here are the signals of technical debt:
- “Code smells”: characteristics in the source code that indicate a deeper problem. You can identify code smell by using automated code review tools.
- Growing levels of complexity: several technologies overlap each other.
- Expansion of backlog on a daily basis: as the backlog grows, the productivity drops, respectively.
- A growing number of bugs: if the number of bugs is getting out of hand, it can be a sure signal of technical debt being present.
- Rising frequency of hotfixes: if you observe that hotfixes occur more and more often, it’s a sign of a problem.
- Diversified coding style: sometimes, when there is a diverse coding style, it can be another indicator of technical debt. Luckily, this particular issue can be resolved by introducing coding style guidelines.
Of course, these are not all symptoms of technical debt but the most common and obvious ones. We highly recommend monitoring your backlog constantly in order to ensure there are no pending or unnecessary items.
How to manage and eliminate technical debt
We are finally getting closer to the number one question which is how one manages technical debt. Sure, the method will depend on the severity of the debt and on your project so we will list down the most common and efficient methods.
Assess the debt
As long as your technical debt comes in the form of pending tasks in the backlog, you will ignore it for a long period of time. However, if you calculate how much it would cost developers to reduce the current debt and how much it would cost with every new day of delaying the fixes, you’ll look at it differently.
You can also use specialized automated tools to calculate technical debt or you can do it by using the TDR (technical debt ratio) formula (which is quite complicated, to be honest). Either way, once you translate pending tasks into dollar signs, the whole situation will become much clearer and easier to assess.
Acknowledge the debt
Another big mistake that a development team can make is ignoring the debt or pushing it to the farthest corner of the backlog in an attempt to “deal with it later”. Hence, what you need to do is:
- Move the fixes to be done to the active tasks so they become visible;
- Communicate the issue to the whole team so everyone understands there is technical debt that needs to be worked on.
As well, it is important to acknowledge stakeholders about the issue and inform them about the real cost of existing technical debt.
Choose an option of “paying the debt off”
When it comes to actually resolve technical debt, you have three options to choose from:
- Ignore the debt. This is an option for the cases where technical debt is quite small and it will take more time and money to fix it.
- Refactor the app. This is aimed at improving the internal structure of the code without touching the behavior of the app.
- Replace the app. This is a more “global” yet highly efficient solution when you have enough time and resources to just fix everything from the start.
Sometimes it’s easier to rewrite the whole product from scratch. Though you can also try covering it with tests and breaking it down into smaller chunks to apply fixes to them
Alex, Android developer at SoftTeco
Balance sprints wisely
Another efficient way to manage technical debt is to leave one day per working week and dedicate it solely to resolving pending tasks. In this way, the team will not get distracted while working on new features and at the same time, will be addressing the existing issues.
Continuous integration and continuous delivery can significantly facilitate the release process as they imply automation of a number of tasks and using a version control system. In this way, the project becomes more organized and more transparent, making the technical debt more manageable.
There were cases when we received a project with huge technical debt and had to negotiate with the client about the possible solutions. It often happens that a client is not ready for the system refactoring so we propose to synchronously work on implementing new functionality and eliminating technical debt. For that, we suggest bug fixing and refactoring of the most critical parts of the code. As well, it’s a common case when a project (system) is too old. So throughout the years of work, everything changes: technologies, approaches to writing code, opinions, and requirements, system load, even team members. In this case, technical debt is almost inevitable as old planning can not be applied to new processes.
Leonid, Head of PM/BA at SoftTeco
Even if your technical debt is caused by “good reasons”, it’s still bad as it harms the project and causes your team to lose productivity and focus. While you can fix it “on the go”, the best option is to prevent it by improving your management practices and possibly introducing new ones that would help prevent the issue and keep the workload properly balanced.