This artilcle was updated on 7 June, 2024
Technical debt is a fact of life in software development. If you skipped our first article or glossary term on the topic, here's a quick review of what it is.
When teams choose a faster and simpler solution over a more reliable one
In these situations, a team collects debt in the form of poor code quality or lack of testing that will gather interest over time. This interest will need to be paid by means of refactoring code or updating libraries and services, which require extra time and other resources. The scope of the work involved in "repaying" tech debt depends on the sacrifices the team made as well as the type of debt. Very basically, there are 2 types:
- Deliberate or intentional technical debt: a team understands that they will skip some steps to meet a deadline or release the product soon. Ideally, they have a risk management plan in place to deal with the debt later.
- Unintentional technical debt: a team lacks a proper workflow or risk management plan and ignores or overlooks the fact that it is skipping steps in the development process.
The costs of tech debt
Human cost
As we mentioned in our previous article, tech debt can negatively affect a product's performance. There is also a human cost to tech debt because it's a burden for every team member and makes the team as a whole unhappy and less productive. For a project manager, technical debt means slower feature delivery. For a developer, the simplest action, such as adding a checkbox, requires more effort, which in turn leads to them having to explain why they're taking so much time to complete simple tasks. It's demoralizing.
Frustration grows as team members start blaming each other. They might feel that their professional relevance is slipping away. Furthermore, accumulated technical debt creates significant delays with feature releases and negatively influences the codebase's general evolution.
Over time, everything becomes difficult. The team resists incorporating new design and architecture practices and postpones implementing new features. They don't touch anything because every change makes the problems grow like a snowball.
Business cost
Technical debt negatively impacts the team, the product, and, thus, all the business processes. New features can't be added, architecture can't be improved, and the product stops responding to market demands. Product scalability tends toward zero, and your business starts losing its customers. The result? Profits stop increasing.
Proper tech debt management is the key to avoiding these costs on your team and business.
Managing tech debt
In case you're experiencing any doubts about whether or not you should invest in managing your tech debt, consider these questions:
- 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 hasn't been reviewed?
At Mad Devs, we have clear answers to each of them: nothing good for #1-2, and you can't for #3. We'll share our process of managing tech debt to provide you with a good example of how you can implement these essential steps into your software development process.
We frequently work on projects initiated by other teams, so we often have to deal with accumulated technical debt. Before we begin, we explain to the client that implementing every new feature will take much more time if we don't deal with the debt. We also show that the possibility of bugs and errors in the future increases and that it could come to the point when it's easier to write a new solution from scratch than struggle with the accumulated technical debt.
We don't want that, and neither does the client, so we follow this plan:
- We document tech debt: We create tickets, add them to the epic, and add a ticket description in the code.
- We write tests: We start working with tech debt when the code's been covered by tests. No tests lead straight to more bugs and larger debt.
- Finally, we "pay off" the tech debt: We refactor code, update libraries, add interfaces, modify the project architecture, implement new tools (e.g. Redis), and take other, similar actions.
Besides these three steps, Mad Devs' developers adhere to principles throughout their work: they take accountability and own their code, including mistakes and debt. Our developers are responsible for their code even if they move to other projects. They understand that refactoring won't happen by itself without proper planning. Finally, tech debt is not something to be ashamed of at Mad Devs. It's a fact, and we are honest and transparent about it.
Tech debt management action plan
We always have a clear plan for managing accumulated debt. This gives the team and the customer a distinct understanding of what part of the tech debt we're going to resolve at a given point in the project.
Here's how we determine the volume of accumulated debt:
- We analyze the code base and other project parts to check whether there are any issues.
- We make a list of issues.
- We analyze the roadmap to see what technical debt needs to be solved to implement the needed features faster and make the product more scalable.
- We edit the roadmap if needed.
- We discuss the necessary fixes with the client.
- We resolve the tech debt and implement the desired features.
When a project has accumulated tech debt, we devote around 20-30% of tasks in every sprint to managing it.
Tech debt management in Jira
We use Jira to visualize the volume of tech debt and track the progress on resolving the debt.
Here's how we organize and solve the tasks:
- We create an epic called Technical Debt.
- We create tasks.
- We assign someone to each task.
- Those responsible for the tasks evaluate how much time it will take to complete.
- We set deadlines.
With these steps, we clearly see what tasks are left, how much time each will take, and their progress. This helps us effectively manage the tech debt and understand how much time we need to devote to it.
We demonstrate the work to the client
Of course, we're not just working on removing tech debt but optimizing our client's product. At this point, we show them what we've done. This is difficult when the client doesn't have a technical background, which is why we employ several methods in our demonstration:
- Test coverage: the more code is covered by tests, the lower the possibility of bugs and errors. We aim to cover 100% of the code in tests.
- Website speed metrics: higher speeds mean some issues were solved.
- User complaints: a drop in the frequency of complaints about errors means we fixed some problems.
- Fewer code lines: bulky code is bad code and not transparent. We make code clear and transparent with fewer lines.
- Changes in the architecture: we show it before and after.
- Cycle time: when the deployment time for a new feature decreases, this means that technical debt has been reduced.
- Stability growth: when implementing a new feature requires fewer changes in other parts of the system.
We like to be succinct when talking with our clients to connect technical debt to their business. For example, instead of saying, "We need to refactor the code," we describe how the majority of the product's failures are connected to a particular low-quality part of the code. If we improve it, users will engage with the product more willingly, increasing its ROI. This approach allows our clients to understand the importance of managing tech debt.
Other considerations
The Big Rewrite: solution or not?
We mentioned that if left unmanaged, tech debt may result in a situation where it's better to rewrite a product's code from scratch. Some developers may say this is the best solution for accumulated debt, but we disagree that "The Big Rewrite," the name for this "solution," is a wise action to take.
After "The Big Rewrite," the product remains essentially the same but with appropriate procedures and processes. If all goes well, the users are then migrated to the new version of the product in batches. Sounds good, right? Not quite.
This process consumes a significant amount of time and resources. In reality, you'll need to develop and maintain two projects instead of one until the entire user base has migrated to the second iteration of your product. Don't rely on "The Big Rewrite" as your safety button, but manage your tech debt within your development cycle.
Mechanism design theory
As you've hopefully noticed, resolving tech debt is a part of our work process. It's not a separate step or something we do when we have extra time on a project. Doing this ensures that we manage our debt in a healthy and efficient manner. If this isn't the case for your development teams, mechanism design theory may help you create a proper tech debt management culture.
Mechanism design comes from economics and is a means of achieving desired outcomes by building incentives based on an individual's self-interest. In tech debt management, the desired outcome would be the reduction of this debt. Likewise, the incentives could be recognition or bonuses to teams that actively work on decreasing the amount of debt on their projects. To make this work, it's important to remove any shame surrounding tech debt so that developers are willing to acknowledge it and report on their progress in removing the debt.
Reducing technical debt with Agile practices
Agile practices are a recurring approach to project management and software development that lets teams deliver value to clients faster and with fewer problems. This approach helps teams achieve the points above over the long term. 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 the number of bugs means that QA has to dig through several 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.
In an agile approach, the central part of the code base must always be ready to be shipped. 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 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 process efficiency. It uses internal integration, team communication, and automation tools. DevOps and Agile are often interlinked.
DevOps is often seen as a solution to technical debt, as it helps analyze and eliminate it. However, DevOps' real strength is its fundamental dynamism, which can be an excellent source of fighting technical debt. In DevOps, nothing is static; 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.
Bottom line
It's impossible to avoid technical debt completely. Accept that fact, but also realize that you can approach your tech debt with maturity and minimize its effects on your product in the long term through proper debt management. Follow Mad Devs' example and include tech debt resolution into your development cycle and sprints to make it a habit.
Mad Devs' engineers never leave the project "as it is." For us, tech debt management doesn't mean that work on new features will stop. We implement new features and fix accumulated issues along the way.
Do you have any more questions about tech debt and how to manage it? Or have a software project that's burdened with debt? Contact us, and we'll put our team to work for you!