Project managing your way through technical debt
Technical debt is something most people would prefer to ignore. (Editor's note: I know I would). The term does induce dread for a reason. Ask any agile project manager.
If you somewhat reluctantly opened this article, we get it. No one wants to talk about technical debt, because most people aren’t 100% sure what is within their company or what they should even be doing about it.
Because of this, we tend to settle for a vague sense of unease surrounding the term alongside a resolution to not let “technical debt” stack up in our companies. Then, we cross our fingers and move on with our projects. Agile teams especially tend to accept technical debt as just a part of doing business.
But the worst thing you can do with technical debt is ignore it. That just makes it harder to deal with later. So here's what it is, why you should approach it strategically, and how you can manage projects within an Agile framework.
What even is technical debt?
Technical debt is a metaphor that describes the cost of choosing faster, short-term solutions that necessitate more work in the future, either through refactoring or the need for additional “Band-Aid code.” Technical debt is also sometimes referred to as “code debt”
You have credit cards. Maybe too many. And you might have to occasionally remind yourself that those cards are not free money. You still have to pay the full price of that new iPhone. You just don’t have to pay cash today.
When you’re under the gun to deliver, quick-and-dirty code might seem like the best option. And there’s a good chance it is the best option, under the circumstances. But it doesn’t mean you’re off the hook just because you delivered the code without issue in the moment.
Sooner or later, you’re going to have to pay for the time you saved, and that "code debt" comes with interest.
Technical debt according to an Agile author
Agile Manifesto author Ward Cunningham coined the term “technical debt” and uses the word “debt” specifically to describe how shortcuts, stop-gap solutions, and otherwise less-than-stellar code borrow against the future stability of your software.
In Ward’s own words, “A little debt speeds development so long as it is paid back promptly with refactoring. The danger occurs when the debt is not repaid.”
In other words, technical debt isn’t necessarily negative. Much like financial debt, technical debt can be useful, even necessary. But reckless use of shortcuts amounts to too much financial borrowing. You can keep pushing off payments until “tomorrow,” but the bill will come due, and you’ll have to pay for it with lengthy restructuring and refactoring. Well, maybe not you, but someone within the engineering organization and they'll at least complain about you a lot while they're doing it.
Ward goes on to say, “Every minute spent on code that is not quite right for the programming task of the moment counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unfactored implementation, object-oriented or otherwise.”
Where does technical debt come from?
Technical debt can stem from many sources, the prime suspects being design flaws (intentional or unintentional), legacy code, system or code migrations, insufficient documentation (leading to inconsistent practice), poor sprint planning that ends in rushed work, and an engineering founder who maybe worked a little too fast ahead of the company's initial presentations for funding.
The exact technical nature of the debt doesn’t really matter—the metaphor can be useful in many cases. The point is to manage technical debt and keep it from becoming a problem. To do that, you first have to understand the nature of your particular debt.
In his Technical Debt Quadrant, author and developer Martin Fowler identifies four types of technical debt. These types exist on the axis of Reckless/Prudent and Deliberate/Inadvertent.
In other words, you take on technical debt in one of four ways:
- Deliberate + Reckless: You make a conscious choice to accrue technical debt, but you do it for faulty reasons.
- Deliberate + Prudent: You make the strategic choice to take on debt to satisfy priorities.
- Inadvertent + Reckless: You generate technical debt based on a lack of thoroughness.
- Inadvertent + Prudent: You did the best you could with the resources and knowledge available, but you realize postdelivery that you should do things differently and better with future coding. By adopting a new standard moving forward, you inadvertently create technical debt.
Once you become aware of how and why your team accrues technical debt, you can take the appropriate steps to limit the negative effects.
Ultimately, technical debt is a highly useful metaphor for discussing a complex problem in a way that makes sense to managers, clients, and other nondeveloper stakeholders.
So what makes this relevant to your business, and not just an interesting linguistic exercise? The same thing that makes financial debt relevant to your wallet: interest payments.
Why technical debt can hurt Agile teams in the long run
Every time you build new features on top of subpar code, every time you slap a Band-Aid onto a design flaw, every day you push off migrating or refactoring code—that interest payment gets a little larger.
And just like interest payments for your credit card hurt your overall financial flexibility, technical interest payments limit your ability to stay Agile in the long run. Principle eight of the 12 Principles Behind the Agile Manifesto states:
Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
Unchecked technical debt makes your development pace unsustainable, while making it harder for agile project managers to track progress smoothly. In an ideal world, working with clean code and good design, you can make delivery estimates and sprint timelines with a fair degree of accuracy. It’s like having your car pass inspection with flying colors—you know it’s reliable, so you can plan each day of your road trip without worrying about breakdowns.
You don’t have that luxury with technical debt. These little “interest payments” steal time and resources, but they don’t do it on your schedule. If you’re not careful, you might be near the end of your sprint before some bad code rears its head and requires an extra week of work to fix properly. Keeping track of your technical debt is key for project managers to have full transparency of the project.
More likely though, frequent refactors will take up more and more of your sprints. This will either slow down deployment or tempt you to take on even more debt to hit deadlines. (Pro tip: taking a loan from one bank to repay another is not a solid plan.)
One day, the bill will come due, and you’ll have to pay for it with lengthy restructuring and refactoring.
Technical debt also creates a codebase that looks like a Jenga tower—eventually, you reach a point where the structure can’t support the things you need it to do. This systemic fragility builds over time and creates more problems the longer its ignored. Ultimately, you’ll be forced to do a major refactor in order to restore system stability and continue growing. But, of course, this takes time away from the goal of Agile: delivering value.
So, while in some cases it may be the smart choice to consciously take on technical debt, this is not viable long term. You need a plan for handling interest payments and for paying down that loan.
Dos and don’ts for managing technical debt with an Agile mindset
If you’ve been in business for any length of time, chances are you’ve accrued technical debt. (If you’ve managed to run a successful business without technical debt, then you should write and publish what will be a very successful book series on how you did it.)
Otherwise, you might want to apply some good old-fashioned (and still very popular) Agile methodology to manage your technical debt and keep it from becoming a major problem.
Do communicate the business costs of technical debt.
Agile is all about delivering value, but it can be hard for nondevelopers to understand the seriousness of unchecked technical debt. In order to effectively manage this debt, you’ll need the support of your product managers, stakeholders, and clients. These statistics will help you make that case.
- Forty-two percent of developers’ time is spent on code maintenance tasks—13.5 hours out of the average week is spent on technical debt alone.
- In 2018, the estimated global GDP loss from developer time spent fixing bad code amounted to $85 billion dollars.
- Another study in 2018 found that in the United States alone, the overall cost of poor-quality software was $2.84 trillion.
As with any debt, the longer you put off restitution, the more it costs.
Don’t let technical debt become invisible.
Without transparency, accountability, and regular analysis, you can easily lose sight of those interest payments until they're overwhelming. Learn to read the signs that tell you when it’s time to refactor code, and keep open lines of communication surrounding this.
Recommended read: How to know when it's time to refactor your software's code
Keep tabs on the nature of your technical debt. Don’t just acknowledge its existence; ttake the time to understand it and its current and future impacts. (Agile Alliance offers some analysis questions you can use to get started.)
Do tackle debt in small increments.
You’re an Agile team—small increments should be second nature by now. The same approach that works for paying down credit card debt works for technical debt—start with the debt that generates the highest interest payments, and work from there. (In our case, that means starting with the design flaws or bad code that have the most dependencies or are used most frequently.)
Don’t assume you have to take on technical debt.
Don’t make the mistake of assuming technical debt is necessary for a given situation. When planning a product or feature road map, take a little extra time to estimate the accrual of technical debt. This will help project managers prepare in advance for the debt and plan accordingly.
Ask yourself a few questions once you have this estimate:
- What’s the benefit of delivering this as quickly as possible? What’s the cost in terms of technical debt?
- What’s the benefit of moving more slowly to ensure sustainability? What’s the cost to my client or end user?
- How far would I need to extend our timeline in order to lessen or avoid this technical debt?
You won’t be able to plan for every contingency, of course, but being more deliberate and informed in how you take on technical debt will make it much more manageable overall.
Do identify which debts actually need to be paid down.
“Tech debt zero” is not necessarily the goal. In some cases, the effort to refactor is actually not worth the ROI, even if you do have to keep paying interest. This could be due to the nature of the technical debt—perhaps it exists in an isolated part of the code without many dependencies or in a feature that is rarely used or is being phased out.
There’s also business reasons to avoid refactoring, such as the need to maximize short-term returns by shipping as quickly as possible. Or maybe you know a game-changing event is coming, like an acquisition or a new platform release that makes refactoring old code irrelevant.
Analyze the cost and benefit of refactoring before you dive in, and, again, make sure you focus your refactoring efforts on areas of highest impact.
While this approach can’t solve every conceivable issue, it creates a framework that allows your teams to form a healthier relationship with technical debt. Agile Alliance also has a wonderful in-depth guide to leveraging project management to handle technical debt.
Moving forward: avoid creating more of a mess
Technical debt becomes the monster in the closet only when you shove it into the closet. You’re better equipped to manage technical debt moving forward when you acknowledge, understand, and analyze the role it plays in your company.
But don’t just share this one article with a couple of product managers and call it done. (But definitely share this article with a couple of product managers.) Be proactive as you tackle technical debt. Communicate the consequences of technical debt to management and clients so that they understand the value of “doing it right.” And keep yourself and your team accountable by making the restitution of technical debt a normal part of your software development process.