02 Sep 2021
Ideas for efficient tech debt management
After quick googling, you will find plenty of suggestions on how to deal with software tech debt. But it’s very rare to find a chance to learn some productive behaviors from real projects. This text is different – we share our experiences, that either worked well or failed, allowing you to learn from our mistakes.
In the beginning imagine a typical situation: the development team plans the work – it can be implemented either by a short or long-term solution. The first one will help you to have the working software earlier, though it may cause some challenging issues later on. On the other hand, the second one will take much more time now but will save plenty of time in the future. While weighing short against long term solution, and an agile approach, how to determine which option is better?
Well – the answer is not that simple and such questions are often a part of software development reality. Today I’ll share some thoughts and experiences on how to become better at answering it. You will also learn how to identify the tech debt, reduce the existing one and finally prevent creating a new one. Let’s go for it!
Setting up the tech debt management concept
As many of you know tech debt is quite often being explained through financial debt – you can take it, and afford something today, but still, you are expected to repay it based on the agreed schedule, otherwise, you will end up with troubles.
The same concept refers to the technical aspects of the product, architecture, used tools, but also to the development process, the organization of work, the team, and its level of knowledge. Today we will focus on the code. If we do care about our finances (read: code), then we can afford more (read: new feature takes less time), and as result less often we need to borrow money (read: tech debt). But if you had to take the loan (tech debt), repaying it in time is best what one can do to protect from problems piling up, and the same applies to repaying tech debt – it should be a planned, not reactive, activity. Yet, the question is how to do it.
In our teams, we started with reaching a mutual understanding of what tech debt is – for us it was the result of the cut-corners policy from the past. The next step was to set up a process, a tech debt life-cycle, describe responsibilities – who, when, and how should rise and repay tech debt items. To have all people on the same page, we even arranged a short session to present the idea, gathered feedback, and finally kicked off.
Our tech-debt-man-in-charge was a tech architect who was qualified enough to offer solutions and oversaw the repaying process from the technical perspective while also bearing in mind business profits. In practice, he was presenting the tech-debt needs and setting priorities on a bi-weekly basis. That helped a lot, mostly to focus on what’s most important rather than on what’s nice to have.
We also agreed when the tech debt was acceptable for the team and the product owner, and – obviously – when it wasn’t. More precisely, if by taking the tech debt we had a chance to gain a fast feedback loop earlier, then it was acceptable, but only if we planned to re-pay it shortly. At the same time, we agreed to improve the code and repay tech debt only when it gave us any value, not to create art for art’s sake.
How to repay the existing tech debt
The biggest challenge was to work on developing the product, maintaining it, reducing the tech debt, and preventing from creating a new tech debt – if possible, all in parallel, please.
We started with categorizing the tech debt by its impact on the user (i.e. does it slow us down? if so – how much? or will it simply kill the project sooner or later? will we get hit by a ricochet?). It was a business and technical discussion – so both the product managers and developers meet and debated, estimated, and prioritized items in the tech debt backlog. Later, we also grouped tech debt items to locate quick wins and more time-consuming ones, so it was easier to pick and pull something to the sprint, if possible.
Then, during refinement and planning sessions teams started with labeling items perceived as a part of the tech debt – thanks to it the items were easily filtered and identified. This simple trick allowed us to create a searchable list of items deemed to be worth re-paying. As result, we created the tech debt backlog and realized there’s an impressive amount of work to be done. Then came the moment to think about how to repay it.
It could have been done using multiple solutions, let me mention some of those we used and that brought us the most benefits in a relatively short time and with low cost. You can always use the Pareto principle to support your decision process, but for sure you need to experiment with it to validate what works best for your team.
In our projects, we had multiple teams delivering the code during each sprint. We decided to allocate time they can spend on addressing tech debt on a regular basis. We have considered different approaches for that – either each developer reserved some time for tech debt activities (1), one of the teams each sprint focused only on repaying it (2), or some developers in each team secured some time for it (3)– let’s say up to 20% each sprint to be spend only on tech debt (for us it was up to 1-2 days per 2 weeks sprint). We tested all of the mentioned approaches. Each has some positives and negatives.
Our experiences show that it’s not that easy to plan time for tech debt activities as quite often there’s some unplanned work that goes together with the items in the sprint and you need to decide then what’s more important – to reach the sprint goal or tackle the code that needs attention but can wait a bit longer. However, by planning it, the likelihood we will find time and reduce the tech debt increases.
On the other hand, if we reserved a whole sprint for the repayment activities, quite often it turned out we needed one more sprint to have things sorted out. Not to mention we were “stopped” with the typical development of new features as we focused on improving the code. That wasn’t the best option.
Following, if we dedicated a day in the sprint for the tech debt, then sometimes it was relatively easy to focus on that, but often we needed to stop that and concentrate on the sprint instead. But after all, the mixed, planned approach helped us most.
Among additional solutions to reduce the tech debt we committed to leaving the code cleaner than we found it using the scout approach. As result, we didn’t need to repay huge chunks of the tech debt at once, but we made it regularly, piece by piece which made tackling tech debt much easier. We also did the refactoring in a planned manner – sometimes even as an important part of the sprint scope.
Currently, each team uses a different approach – the one I prefer most is to plan to repay the tech debt each sprint, piece by piece, having reserved team’s capacity for it, let’s say 10-20% of your time, and to never give it up. Ideally, if the team decides who takes care of it on a particular day, so everyone’s happy. Such combined solution work best for us.
How to prevent creating a new tech debt
We need to accept the tech debt as an inevitable part of the development. With that in mind, we brainstormed to figure out which situations forced us most often to take the tech debt. In our case it happened mostly when we needed to implement a quick solution to get ready for the release as soon as possible, there was not enough time because of the deadline, or we were not smart enough to do it better at that point.
These examples became indicators that alarmed us “oh, there’s a potential tech debt around us now” and that helped us to start treating it seriously. By understanding the root causes of the potential tech debt, it was easier to prevent taking it.
One of the ideas we experimented with – and proved to be useful – was to say “no” before accepting to take the tech debt. Instead of agreeing immediately, we always considered the pros and cons. Prior to raising the tickets, we answered questions like “why it was worth taking the debt?” and “what value would bring it for the business (or the user)?”. If we agreed on taking it, then we always registered the ticket to repay it and planned when to do so. We assumed it’s better to do less during the sprint but to do it right.
That was great for the developers, but hard for product owners who expected to do more and more each sprint. That approach needed to be changed as well, so they would also understand the concept of tech debt. It included involving the product and the business team in discussion – after all, we were all in the same boat together. It allowed us to ensure that handling tech debt was considered regularly. As result, we created an environment that allowed the teams felt comfortable enough to refrain from committing to too much at sprint planning.
Easy to say, hard to practice
Finally, we can take a look at the question “what’s better” from the beginning of this article. Well, it depends. If the project is just starting, take the tech debt and validate your ideas quickly, after that, if you still want to develop the product, repay it. If the project is already set, before taking the tech debt always consider the consequences and if decide to take it, then plan to repay it. Otherwise, you will end stuck and who knows, maybe seek for text like that one. There’s no other choice than just to manage the tech debt. Additionally, remember that theoretical concepts work fine till they face the reality, thus presented ideas for addressing it may require additional activities I haven’t described to ensure these would fit your particular scenario.