Question

I've been working for the same software company for nearly 14 years now. Over that time I've seen plenty of technical debt being accrued. I think that is inevitable for any long lived software company.

However, we've never had a strategy for dealing with it. We are aware of the technical debt, people complain about the technical debt, but we rarely build any method of dealing with it into our plans. I know this is part of the reason why people have left our company.

I've done a search, but couldn't find any proven methods for dealing with technical debt?

What I've been doing personally is adding a file called TechnicalDebt.md to my repos with a description of what I think needs changing and why, along with an estimate of time.

The above is my primary question but I expect to have arguments about this, particularly from those who will assert "there should never be any technical debt". So anything you can provide which also makes the case for having an approach to technical debt would be appreciated.

Was it helpful?

Solution

I suspect your question will be closed for being too broad which is a shame as any developer who has been round the track a few times will have encountered this a lot.

But just to share my experiences - there are a number of aspects to this:

Unit tests

Paying down debt will no doubt involve refactoring legacy code. This is all very well, but you will soon become the focus of unwelcome attention if you start breaking things. A good unit test suite should be in place anyway, but if it isn't, get started on it, as these can give you an early warning that your refactorings are going awry.

Approaching legacy code

This is a topic that people literally write books about - the most famous of which can be found summarised here.

The nature of the debt

Not all debt is the same - how your tackle it depends on the nature of the debt. If it is simply an obsolete technology then it could simply be replaced rather than refactored. Hard to give much more advice without knowing specifics...

Getting buy-in

I've worked in places where management are all about features and bugs and simply won't entertain any time being devoted to "polishing". This of course is very short sighted. If you don't get buy-in to fix the problems, you're simply going to have to attend any problems while you're in the code doing other things.

Understand also, that it isn't just management buy-in, you need the buy-in of your peers too. They will have different ideas about how the various problems should be solved. Involve everyone and you'll find the whole process is a lot easier.

What are your rituals?

Some say you should never have technical debt. This is a pretty naive stance if I may say so. Perhaps what they mean is that your debt should be as low as feasibly possible (like household debt).

That being said, how much debt you have is a function of how you view it collectively. If it is always at the front of your mind to pay down debt wherever you find it, you'll find it coming down quite steeply. If you're looking to fix it in your free time (whenever that is), it is a long hard road - not least as you could simply accrue more debt in the time it took to pay another debt.


As for tracking it in the first place, it should be recorded it your usual work tracking tool. How you separate this out from the rest of the work will vary from tool to tool.

OTHER TIPS

The best way that I've found to track technical debt is by tracking it in the issue tracker, along with new features/development and bugs. Depending on the tooling you are using, there may be various options for identifying technical debt, from issue types to some kind of tag or label.

Overall, there are two ways to pay down technical debt.

First, if there's technical debt in the same areas of the application that are being developed, that should be reflected in the estimates of the work. It will take longer to develop a given piece of functionality to the same level of quality if there is a high amount of technical debt. Minimally, an estimate will account for the need to work through technical debt, and the estimate can include effort to pay down the technical debt.

Second, individual work items to track technical debt and pay it down is useful to plan and track work outside of new development. This is especially useful if the features with technical debt may not be under active development currently or in the immediate future. You can track what area(s) of the system changes are being made to in order to have traceability and insight into where to focus testing efforts.

Acknowledge and chart losses

Let's use an example here. If I buy a 1 year membership card from my local supermarket, I get a 5% discount on my purchases. But do I really want to invest the $75 that this membership costs?

For now, let's say that just like how a company doesn't want to spend time tackling technical debt, we've decided not to buy a membership card. After all, I need to be spending my money on groceries.

  • Dec 30 - Bought $200 worth of groceries for the NYE party. I paid $10 more than what I would've if I'd had that membership.
  • Jan 3 - Weekly groceries $60. $3 could've been saved as a member.
  • Jan 10 - Weekly groceries $60. $3 could've been saved as a member.
  • Jan 17 - Weekly groceries $60. $3 could've been saved as a member.
  • Jan 24 - Weekly groceries $60. $3 could've been saved as a member.
  • Jan 31 - Weekly groceries $60. $3 could've been saved as a member.
  • ...

It's a simplistic example, but you very quickly notice that in a month's time, you would've saved $25 by being a member. You don't even need to register the next 11 months to know that you'd be better of with a membership.
Counting weekly groceries alone, I would save $180 per year (for a total of $105 if you subtract the cost of the membership), and that's not even counting the occasional extra expenses.

The important thing to take away here is that recording a fraction of the total time (1 month) immediately revealed a reasonable expectation of of the total time frame (i.e. the year long membership, or the project's lifetime)


Weigh the cost of refactoring against the cost of not refactoring

If you document any time losses and extra effort being spent on things that were caused purely by technical debt, you quickly get an idea of how much time you waste on it, which you can contrast to the time you would "waste" on fixing the technical debt.

There is a relevant XKCD for this:

enter image description here

Look at the math. If your entire team combined on average loses 30 minutes a day on technical debt (which is more than reasonable), then you can reasonably spend 200 manhours (5 weeks) on doing nothing but refactoring and you'd still break even over a 5 year period (which is again a reasonable timeframe for a project).

This calculation isn't even accounting for features that will be added in the future, which would only increase the time wastage if you don't address the technical debt.

I'm aware that technical debt isn't as clearly delineated as grocery bills are, and you're going to have to make a judgment call on whether it contributed to a bug (or its fix) or not. This isn't objectively measurable. It's an estimate, and estimates are imprecise, but reasonable estimates tends to average out over a longer period. If your team cannot make reasonable estimates, then you've got bigger fish to fry.

If you document all tickets that were reasonably affected by technical debt, and estimate the time lost on that (some bugs count for 100%, others only partially, new features incure a % time cost due to a needlessly complex codebase, ...), then you quickly start seeing how much time this debt is costing you.

I suggest categorizing particular technical debts and tracking them separately. It's more meaningful to know how a particular debt is affecting you, so the company is able to only fix the debt which is creating an active issue for their bottomline.

I think that is inevitable for any long lived software company.

It is like saying that decay of any building is inevitable. If a building is never maintained or repaired, then decay is indeed inevitable. But if you take time needed to do proper maintenance, a building can remain in a good shape virtually forever.

Similarly, if you take time to reduce technical dept, the code base may remain in a good shape for the whole life span of a product.

I've done a search, but couldn't find any proven methods for dealing with technical debt?

Lots of software companies provide good examples.

How to you find those companies? By looking at successful products which exist for a very long time. While some (such as Windows) were rewritten from scratch, many didn't: rewriting from scratch is a costly and risky business. One of the well-known products which stand the test of time is Linux. A good thing about it is that it's open source, so you can see how it was developed through time and how developers managed the technical debt.

I expect to have arguments about this, particularly from those who will assert "there should never be any technical debt".

Having no technical dept at any moment is quite costly, and not always useful. While some practices, such as refactoring, should be a constant activity, some others may be postponed until the code is stable enough.

Putting technical debt tasks into a issue tracker is an obvious thing. But that is rarely the problem.

The main problem I experience with dealings with technical debt is that it causes a conflict between business and engineering. It is extremely difficult to quantify a business value for a technical debt issue. Especially if gains are extremely long-term in range of months or years. So getting business to plan technical debt issues over their "critical" new features becomes an impossible task.

Simplest solution is for engineering to set aside constant amount of time for maintenance. My experience shows that 10-30% of engineering time is best when dealing with low technical debt. But the value can go up to 70% when paying back huge amount of technical debt in a way that actually achieves any reasonable gains in the long term. Often, this time becomes something that business should not know about, as they would demand that time to be spent on features instead.

Technical debt creeps in due to a number of factors, including:

  • Tight deadlines - you cut corners to ship product.
  • Changing requirements - the product has to do things, it wasn't designed for.

How much technical debt is acceptable is a business decision - for example if not shipping means you don't get another VC round you probably want to cut every corner you can. Therefore you need to discuss with the business what the impacts of incurring or paying down debt are and develop a plan from there.

Paying Down Debt

Some options to discuss might be:

  • Allocated a fraction of each iteration for debt pay-down.
  • Allocating 1 iteration per quarter for cleanup.
  • An entire project to rewrite a specific module.
  • Allocating additional time on each story - to give developers more time to do a better job.

What does the Business "Get"

That said you are probably going to face one difficult question from the business:

"What do I get for allocating time to cleanup"

In order to be able to answer, you need to be able to say:

  1. What technical debt do we have today.
  2. How much (time) will it take to fix it.
  3. What is the cost of the debt.

Point #3 is really the most important here, if code runs fine, doesn't cause support incidents and there are no plans to change it in the near future. From a business perspective it's an "Interest Free Loan" - there is no reason to pay it down.

Planning

You probably want to put processes in place to track:

  • How much additional development cost is being incurred as a result of each technical debt item.
  • How much support incidents cost - in terms of salary and/or revenue.

The process should record, what technical debt items you currently have and tie future development problems and production incidents back to them. This will allow you to prioritize which technical debt is most costly to the business.

For the most expensive items your should generate a rough estimate of what it would cost to fix each one. After doing this its a return on investment argument for the business - so if you have made a good case you should be able to convince them to allocate time, via one of the previously stated methods.

The business side doesn't care about technical debt, all they care about is shipping product. But, you can do some things to alleviate it.

  1. New code shouldn't accrue any debt. Make sure you have checks and balances in place to ensure this happens on a consistent basis.
  2. Frame technical debt from a business value standpoint. This can be done by looking at your code base and figuring out the worst pain points. It could be that a doing a certain task takes 3 days. If we get rid of the debt, it will take 3 hours. There's some business value in that because product can be delivered faster. If you remove the debt but the delivery time stays the same, then the work you did was for nothing from a business standpoint. So, it is important to get business buy in for those debt reduction stories and measure the impact as well post delivery. There should be some positive impact from a business point of view.
  3. Finally, nothing last forever. If you have a product with many years under it's belt, it may be time to re-platform, that is declare bankruptcy and move on. This will depend on how much value your current product is returning versus the effort needed to maintain and enhance it.
Licensed under: CC-BY-SA with attribution
scroll top