For most businesses in the software industry, the concept of technical debt has come up at some point. Constant competition, the need to meet more and more customer expectations, adding new features to software products – there are many technological choices that can lead to budget losses and disruption of productivity. Some of them cause a so-called technical debt. Here we give a technical debt definition and discuss what the best techniques of technical debt management are.
Ward Cunningham, the author of the Agile Manifesto, described technical debt as the practice of relying on temporary (usually easy to implement) solutions to achieve short-term results at the expense of efficiency in the long run. In other words, tech debt is the consequence of developers taking measures to speed up the delivery of a project (or just a part of the project) that will later need to be refactored, or the result of prioritizing speed of delivery over functionality and quality. Such a practice may lead to errors and deficiencies in the code. Of course, the quicker path doesn’t always have to be bad – it can be used to ensure you’ve got a product that works and meets the deadline. Examples of technical debt include the following:
- untested code,
- unreadable or dead code,
- duplicated code,
- out of date documentation.
Now let’s explain what causes technical debt. Some people incorrectly think that inexperienced or below-average developers who don’t know the best programming practices cause tech debt. However, there are other causes:
- Lack of time – when you work under tight deadlines, your team may decide to cut corners. Very often, especially when a faster time to market is a priority, companies opt for the ‘just ship it’ philosophy. This leads to inconsistencies and bugs in the code and, in consequence, increases technical debt.
- An unmotivated or underqualified team of software engineers who ignore bugs. Sometimes they just lack experience.
- Putting product-market fit first – an obsession with product-market fit is common. Ignoring unresolved issues and messy code can be costly in the long run and can harm the ROI, even though the product-market fit is in place.
- Feature creep – this happens when software requirements increase in the middle of the development process. Plans change and so do sprint priorities. Bugs are left for tomorrow and the technical debt increases.
In agile software development, technical debt usually occurs when the product owner (or product manager) decides to launch a new feature or product and defines a very short time to market. This often leads to bugs in the code. Even if the new feature or product is launched on time, there are accumulated bugs and messy code. This leaves the team with unwanted agile technical debt, which is the implied cost of additional work. Iterative development in agile is ignored, whereas incremental development is preferred. Changes and fixtures that should be implemented in the consecutive sprint cycles are often just left behind.
So, is technical debt bad or good? The truth is, there is no simple answer. Accruing technical issues can cause serious problems and is bad in general. However, tech debt may bring savings if you implement a good technical debt management strategy. It becomes an issue when business managers ignore it. In fact, it all depends on the context and project needs. In some cases, such as when developing a minimum viable product, startups choose tech debt deliberately. The challenge is to balance it in a way that benefits your company in the long run. A well-understood debt should be managed with informed decisions. The amount of ‘acceptable’ technical debt is fully dependent on the project you’re working on.
Like any other debt, technical debt will have to be paid back in the future and the costs can sometimes be significant. First, as technical debt increases, the value you deliver declines. You need more resources and effort to maintain the project’s forward momentum, which reduces the productivity of your team. They have less time to develop new functionalities so the value you deliver is lower. At the same time, the number of bugs and defects in your software product increases which causes further product maintenance costs. Poor performance, malfunctions, data leaks, and security issues – these are just a few examples of possible issues. Another issue arises when the development team is aware of the agile technical debt but doesn’t have the time and resources to fix it: frustration grows and morale decreases. The team is stuck working with a flawed system and completing lots of manual tasks. Thus, they become frustrated. Transparency is reduced and it becomes more difficult to understand the current state of the process. Finally, if technical debt keeps growing, it may turn out that the development cannot be continued any further. This is the most harmful possible consequence of tech debt.
Technically, there are two types of technical debt:
- Intentional tech debt – the team that needs to get its product to the market as quickly as possible or release the update faster creates it deliberately. Intentional tech debt involves a premeditated choice. It represents a known risk that the team can document, track, and remedy.
- Unintentional tech debt – this happens when the team works in a way that leads to accruing technical debt without even realizing it. Such a debt can still be remedied but it will take some time to adjust the development process and revisit the code.
Sometimes, environmental debt can also occur. This is accrued over time and without active effort, e.g. when you fail to keep up with fixing capability issues or when the system is patched.
To better understand technical debt, let’s also explain the technical debt quadrant created by Martin Fowler (Fig. 1). According to the quadrant, there are four types of tech debt depending on intent and context: deliberate, inadvertent, prudent, and reckless. Here is what they imply:
- Deliberate and reckless – a result of bad software architecture. The team focuses on shipping the software product as quickly as possible, believing that they don’t have time to build a better code. The built solution is of poor quality. However, in some cases, it is better to launch a product with technical issues than to allocate time and money to developing the perfect product.
- Deliberate and prudent – this occurs when you cut corners in terms of quality, but you control the process through technical debt management. Such debt is small as it is mostly related to code that rarely needs modification. The team is fully aware of potential problems they will need to handle later on.
- Inadvertent and reckless – this happens when the team doesn’t have enough knowledge and experience. Thus, they cannot manage the agile technical debt. This is probably the worst type of technical debt. The team doesn’t recognize it the moment they incur it.
- Inadvertent and prudent – this is not a result of neglect as it occurs when the team realizes that they could have built a better product after the product is delivered. Such debt happens despite caring about quality.
Fig. 1 Technical debt quadrant by Martin Fowler
Some amount of tech debt always exists. In most cases, accepting it is better than wasting resources fixing it. Technical debt can be okay when you are building an MVP, or you have an experienced team of developers who understand technical debt management. Below you will find the most popular strategies for managing technical debt:
- Make sure that the entire team is on the same page when it comes to technical debt – developers, managers, and stakeholders have contrasting viewpoints. To manage technical debt, everyone should understand that the debt has negative effects such as higher costs and a slower time to market. What is more, a timeframe and activities to mitigate the technical debt should be clearly defined so that everyone can collaborate and resolve conflicts of interest easier. This may require some changes in an organizational culture to encourage teams to talk about challenges.
- Introduce code standards and reviews – create a collection of programming rules and best practices. Putting quality over speed in most cases pays off. Programming standards reduce technical debt in the long run. You can also ‘pay the debt off’ regularly every single sprint. This is a great way to mitigate it. To do that, embrace agile software development practices.
- Balance sprints – try to keep a day in the week (or more) for managing pending tasks. An ‘extra’ day for big fixes in existing features increases effectiveness and mitigates tech debt.
- If there is problematic code, start refactoring it to make it more maintainable and understandable.
- Implement automated testing – especially in agile projects - this makes it much easier to detect bugs and errors. Automated testing can be a great help in validating the quality of the code and end product. It’s also a chance to eliminate manual testing. Implementing automated testing also includes introducing CI/CD into the process. Do you want to know more about automation testing? Check our recent article about QA automation for more details.
Most startups and software companies at some point have to make some suboptimal decisions. Such decisions often contribute to technical debt. Even if you cannot avoid it, it is crucial to learn how to proactively manage it. Start with checking code quality on a regular basis. Make sure your team is aware of what technical debt is and show them how to manage it effectively. Short-term wins are easy to have but long-term work involves much more effort. And finally, especially when it comes to agile technical debt, focus on automated testing – a part of the process that is extremely important and often skipped over.