Software development is a highly volatile industry where new project management tools, frameworks, and methodologies come and go as quickly as we can come up with new buzzwords.
Some methods, like lean development, make more sense than others, but not a single new method, trick, or technique can argue with the fact that “the quality of work is constrained by the project's budget, deadlines, and scope.” Sometimes, we can bend the game rules to a degree, but entirely breaking them is never an option.
In this article, we’ll break down the meaning of technical debt, discover its types and reasons it happens, and also analyze how to fix it.
What is technical debt?
Technical debt is the price a company will pay later for choosing a simpler, faster, yet less reliable option today. Any compromise you make to release products or features faster in the present will accumulate a greater volume of work to do in the future.
Moreover, technical debt—just like any other form of debt—accumulates interest unless carefully taken care of.
The so-called interest makes new feature releases more expensive and less stable. Your team will be wasting time dealing with compatibility issues and bug fixes. They won’t be able to focus on the actual development of new functions.
Is technical debt always bad?
As a matter of fact, technical debt isn't always bad. In fact, technical debt is almost always unavoidable when there's a compromise between speed, cost, and quality. Technical debt might become a severe issue only if the managers ignore it or due to poor engineering decisions.
Types of technical debt
American developer Steve McConnell in 2007 suggested that there are two types of technical debt: intentional and unintentional. McConnell says intentional technical debt is technical debt that is taken on thoughtfully, as a strategic tool. On the contrary, he calls unintentional debt “the non-strategic result of doing a poor job.”
Let’s take a closer look at what types of technical debt exist.
Planned technical debt
If you truly understand the risks and costs but are still ready to release the product early, that’s planned technical debt. It happens when you make an informed decision and realize the compromises you’re making. In order for the planned technical debt to run smoothly, you need to calculate the risks and be precise when estimating the workflow.
Unintentional technical debt
Unplanned technical debt happens when you have one of the following:
- Poor practices
- Inexperience with new coding techniques
- Rollout issues
If you released a design with too many faults, that’s unintentional technical debt. Often, unintentional technical debt is the result of poor communication between developers and other team members.
If there are any changes in your business structure or new technologies arise with passing time, that might cause unavoidable technical debt. It might happen mid-project when extra scope changes are requested, which results in an immediate rise in costs.
Technical debt Quadrant
American developer Martin Fowler suggested another way to categorize technical debt by type in 2009. Technical Debt Quadrant is based on intent and context of technical debt. According to Fowler, technical debt can be classified based on intent: is it deliberate or inadvertent? After that, the question is whether it is prudent or reckless debt.
- Reckless and deliberate: When the team might know about expected troubles, but goes on with speed over quality.
- Prudent and deliberate: When the team fully understands consequences but decides to ship and deal with them later.
- Reckless and inadvertent: When the team lacks experience and implements the wrong solution, not knowing there will be a mess.
- Prudent and inadvertent: When the team realizes what the solution should have been only after the deployment.
Another classification of technical debt
In 2014, a group of academics rethought the categories suggested by McConnell and Fowler and proposed classifying technical debt by its nature rather than whether it was strategic or not. They were sure the existing ways to categorize technical debt didn’t address the specific nature of the debt.
The resulting paper, “Towards an Ontology of Terms on Technical Debt'' was published by the Software Engineering Institute. It states that there are 13 distinct types of technical debt:
- Architecture Debt
- Build Debt
- Code Debt
- Defect Debt
- Design Debt
- Documentation Debt
- Infrastructure Debt
- People Debt
- Process Debt
- Requirement Debt
- Service Debt
- Test Automation Debt
- Test Debt
What are examples of technical debt?
Let's analyze technical debt based on one example of current interest. The Covid-19 pandemic has changed many things about our everyday lives, including the way we shop online. Many retailers already had websites and mobile apps, but they were not ready for the influx of online customers due to the pandemic. The websites and apps existed in the place, but weren't initially developed scalable enough to work with the flow of concurrent users.
On the other hand, those retailers whose websites and mobile apps were properly developed didn’t face any issues, such as Amazon and AliExpress.
Causes of technical debt
Several things can lead to technical debt, so let’s take a look at them.
- Time pressure: Developers often face the pressure to deliver the product on time. This might lead to the deployment of apps that are not fully featured or contain bugs within. In order to get to the market as quickly as possible, development teams might sacrifice the performance of an app.
- Market change: Even if you release a fully-featured app, you might face customer expectations changes. New market opportunities might be challenging for a company.
- Outdated technology: To develop an application, you need several coding languages, developer frameworks, and libraries, which can become obsolete and not supported with passing time.
Mad Devs’ position on technical debt
With time, software tends to accumulate cruft. Those are deficiencies in the software quality that make it difficult and costly to extend or modify the software in the future. Why do we use the word “debt” though? We can compare software technical debt to a financial one. You repay it not just with the sum borrowed but with interests. When you need to extend the system, you need to make an extra effort to implement the extra features. This extra effort is the interest you pay for the technical debt.
For example, we need to implement a feature. If the system is developed properly, the new feature implementation takes several days. But if the system has accumulated technical debt, we add the time and effort needed to implement the feature to the time and effort needed to handle the accumulated cruft. Say, the entire process will take seven days instead of three. So, four days are the “interests” paid for the technical debt. At some point, it will be easier and cheaper to develop a new solution instead of sustaining the old one.
The best way to deal with technical debt is to treat it like a financial one - pay the ‘sum’ of debt part by part. Spend a couple of days to defeat cruft in your code, at least party. There’s a chance it might be enough for now - like you pay credit debt percentage so that you can repay the whole debt one day. This extra time to work with part of the technical debt makes future feature implementation cheaper.
Mad Devs’ engineers never leave the project “as it is”. Even if the previous team has accumulated heavy technical debt, we manage it by prioritizing tasks correctly. Technical debt management doesn’t mean that the work on new features won’t move on. For us, it means that along with the implementation of new features, we are fixing the accumulated issues.
Why do projects fall victim to technical debt?
Two primary reasons companies tend to tie themselves in technical debt: Time & Money
Any business, big or small, needs new features. Fast! So there’s no wonder borrowing time and financial resources seem like a legitimate solution.
Most startups are underfunded. Apart from the competitive and volatile markets, the lack of resources is often cited as the primary reason leading to product failure. In other words, two out of the three sides of the iron triangle are off the table before development even begins.
And yet, both young entrepreneurs and seasoned veterans of the investment scene take the risk. Everybody wants to be in the 1% of successful small companies that make it to the top.
Few truly care about technical debt because technical debt is not the main factor determining whether a startup will promptly raise investment. These factors are the time to market, competition, and the growing user base.
Then there are enterprises: the gargantuan players that are quite slow when it comes to adopting change. These companies have spent years and decades perfecting business processes that are tailored to maximize profit and ROI.
More often than not, these companies are run by people with a business-first mindset without a strong background in IT. Sadly, they see development as a bottomless pit of unnecessary investment.
Why waste $100K on refactoring if the product works as is?
Why invest in experienced coders when middle or junior engineers are speaking the same language?
Why waste time designing architecture when the market demands new functionality?
These and similar questions trouble the minds of decision-makers and product owners with a business background.
The simplest solution is not always the best one
Building a product for 100 users without a solid “foundation” will work just fine in the present, but will fail once the user base grows to 1000 users. The absence of a reliable development methodology is easily missable at first. But then things can go sourly wrong.
Given the circumstances and the continuous time-budget constraints, many companies and vendors fall victim to saving on all the wrong things:
- Software architecture
- Infrastructure planning
- Knowledge management
Think about this:
- What will happen on a project without documentation when new team members are onboarded?
- What will happen to your website’s or app’s live version when a new feature is introduced without being tested for compatibility?
- How can you be certain of the overall quality of your code if it has not been reviewed?
The implications of being in debt to your own product
Large technical debt affects the bottom line
What do you do when a website you’re trying to access fails to load quickly? The odds are you’ll leave to look for a different website. In fact, 53% of mobile users will leave if a website fails to load within 3 seconds.
The same can be said about any product that continuously experiences downtime due to the system’s painful introduction of new features.
Services that rely on impulse sales are probably the best example. Especially in the transportation industry, where customers interact with the taxi service continuously, such downtimes create inconveniences in the established routines. People run late, annoyed by lagging applications, and taxi drivers lose their profits. Moreover, transportation is a competitive market, where competitors bombard users with promo codes and offer a service that always works. Over time, each downtime shrinks the customer base.
Similarly, large projects will lose their client base over time if they continuously expose their clients to bugs and downtime.
Why technical debts lead to The big rewrite?
If the system is deep in technical debt, there will come a time when sustaining it is no longer effective and even counterproductive.
If the risk of implementing fixes or new features is too great (for example, a bank or a financial system cannot afford downtime), the product needs to be remade from scratch.
This new system is called an Antipattern: The Big Rewrite. It’s essentially the same product built from the ground up, but this time with appropriate procedures and processes in mind. If all goes well, the users are then migrated to the new version of the product in batches.
The big rewrite may sound like a reasonable solution to the challenges of technical debt, but only at first glance. In reality, you will need to develop and maintain two projects instead of one until the entire user base has migrated to the second iteration of your product.
Then there’s the reason why the antipattern has earned its name: more often than not, a newly rewritten system never gets to production as it can’t keep up with the features developers are introducing into the original system.
Alas, the only alternative is a broken solution and the eventual loss of the entire user base.
Ways of fixing projects stuck in technical debt
Are there alternatives to introducing an antipattern? Sometimes yes, and sometimes no. The availability of solutions will depend on the severity of the situation you have ended up in.
In the best-case scenario, you are working with the original team that has been working on the project since day 1.
Steps to take:
- Working closely with the team. Getting everything from their heads into cohesive documentation.
- Analysis of the issue tracker: info in the ticket description, labels, and assignees can shed much-needed light on the state of your project as a whole.
- Implementing change through tests. This means that the tests are written before coding. That’s how you ensure the system stays intact and is not affected by the implementation of fixes.
This scenario usually occurs when a business has gone through one or more development teams over the course of the development cycle.
Steps to take:
- Technical archaeology: an attempt to understand and document the system.
- Analysis of the issue tracker.
- Introduction of fixes and issues through testing.
How to manage technical debt on a budget
What about operating on a budget? Can a development team deliver a successful project without investing an arm and a leg?
- If you are working on an MVP, and ONLY if you are willing to re-develop it from scratch after raising additional funds, you can skip some of the most time-consuming processes in favor of time-to-market delivery.
- Alternatively, you can go back to the Iron Triangle. Taking the price side away, you will be left with time and quality. This means that you can develop a fantastic product without skipping any important business or project management processes. Prepare yourself for long-term estimates. Unfortunately, this approach is the only viable option when it comes to creating scalable, future-proof projects.
- Lastly, if you had a viable reason to skip one or several development processes, create a preemptive ticket to fix the issue in advance and label it “technical debt.” This way, you will always keep tabs on the bigger picture without borrowing too much, or at least you’ll help your future self with sorting out the mess. In either case, technical debt is much easier to cope with if it’s well-documented.
Reducing technical debt with Agile practices
Agile practices are a recurrent approach to project management and software development. It lets teams deliver value to clients faster and with fewer problems. An agile team separates its work into small parts, tasks, and sprints. Results are reviewed on a regular basis which gives the development team an opportunity to work with problems as fast as possible.
In traditional development, ‘done’ means ready to be tested, but there are so many bugs that it’s painful for QAs, and when they start, there are layers of defects. There is no ‘done’ in the agile approach as iterations of work are delivered to users with bugs fixed and functionality improved.
As a rule, in an agile approach, the central part of the code base must be ready to be shipped at all times. What's more, there are automated tests and feature branching workflows. New features are developed on a task branch containing code for the feature itself. Once it is complete, the unit can be merged up into the main one. This way, the technical debt stays under control due to the quality bar.
What is technical debt in DevOps?
DevOps is a set of operations that combines software development and IT operations to maximize the efficiency of the processes. It uses internal integration, team communication, and tools for automation. DevOps and Agile are often interlinked.
DevOps is often seen as a solution to technical debt as it helps to analyze and eliminate it. DevOps' real strength is its fundamental dynamism, which can be an excellent source to fight technical debt. In DevOps, nothing is static, and everything will change. The dynamic process of self-renewal is at the core of DevOps, so eventually, technical debt will be eliminated in the process of renewals and renovations.
It’s always impossible to completely avoid technical debt, but it’s possible to be mature about it and minimize its effects on the product. The main thing is communication between developers and the management team.
Got any more questions on technical debt? Have a brilliant idea for software and looking for the right developers? Just contact us and we’ll do everything for you.