In 2003, Martin Fowler explains the metaphor of technical debt as follows:
You have a piece of functionality that you need to add to your system. You see two ways to do it, one is quick to do but is messy – you are sure that it will make further changes harder in the future. The other results in a cleaner design, but will take longer to put in place.
Technical Debt is a wonderful metaphor developed by Ward Cunningham to help us think about this problem. In this metaphor, doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into the better design. Although it costs to pay down the principal, we gain by reduced interest payments in the future.
The metaphor also explains why it may be sensible to do the quick and dirty approach. Just as a business incurs some debt to take advantage of a market opportunity developers may incur technical debt to hit an important deadline. The all too common problem is that development organizations let their debt get out of control and spend most of their future development effort paying crippling interest payments.
Some reading this may question that managing technical debt should be in the purview of product management. Since product management is responsible for defining what a product does and engineering is responsible for how it is implemented, dealing with technical debt appears to fall squarely in the engineer’s realm of implementation. If a piece of code accomplishes what a product manager intends, why should a product manager be involved with how the code is written?
Product managers should be concerned with technical debt because (A) their timeline requirements can be the cause of technical debt and (B) their role in prioritizing engineering tasks can either help or obstruct the paying off of technical debt. If a product manager constantly forces the engineering team to deliver features the quick-and-dirty way and refuses to prioritize the subsequent refactoring of the code, the product and team becomes a ticking time bomb. With deficiencies in the code compounding, feature development will halt to a slow crawl and the engineering team will likely revolt, saying that management isn’t allowing the creation of clean code. Products can fail due to technical debt — the product manager is accountable for the success or failure of the product.
Yet, teams can err in avoiding technical debt at the wrong time. A primary principle of product development is validating or invalidating product ideas as quickly and cheaply as possible. If the engineering team spends extra effort building a feature the “right” way, that incremental time spent will be a waste if the feature ultimately fails with users. And if the engineering team invests in a project to refactor an area of poor code, that effort never cashes out if that part of the system isn’t required to change again.
It is not healthy for a product manager to be over involved in how a product is coded. Product managers are not engineering managers. It essential to preserve the line between the “What” and the “How.” However, product management can inform their engineering partners on the right times to avoid or accumulate technical debt and the right time to pay it off or ignore it.
For example, let’s say your engineering team is telling you that, to reach the last deadline you put forth, the code for searching records in your system shipped with serious deficiencies. Now that the deadline has been met, they want you to prioritize a task immediately to refactor the search code, paying off the technical debt. While you want to be sensitive to this issue, you’re aware of many other pressing business needs. It’s painful to prioritize a refactoring effort that will be invisible to the end user.
What should you do? Should you please the engineering team by immediately prioritizing the refactoring or leave folks uneasy by shifting focus to something different, leaving the hacky code as is?
The answer to this question comes down to how certain you are that this area of the system will have business demands to grow in the future. If the search functionality never needs to evolve, the business will have nothing to show for an effort to clean it up. But you can’t predict the future. This leads to a core principle of managing technical debt:
The most profitable time to pay off technical debt is as part of an effort to add another feature to the system in question.
Resist prioritizing engineering “chores” that have no purpose other than cleaning up code. But when the business requires an enhancement to a problematic area, ask engineering to spend cycles on cleanup as part of feature development, even if it slows down delivery. This strategy has these advantages:
- It helps you only invest in refactoring areas of the code that actually need to grow. I.e., you avoid cleanup efforts that never cash out.
- It gives refactoring efforts a clear focus; i.e., engineering can improve the code to easily support new features such as the actual one the business needs, not hypothetical new features that will never come to fruition.
- It signals to the engineering team that you understand the importance of clean code, while constantly moving your product’s feature set forward.
This principle of paying off technical debt is predicated by the reality that the time pressures on a product development team go in waves. While many teams feel that they are constantly under intense heat, time pressure is always a relative scale. When you’re on the side of the spectrum where your company will crumble if you don’t deliver feature X tomorrow, you won’t be able to pay off technical debt and you’ll be accumulating more of it. But when you’re on the opposite side of the spectrum, it essential that you use that time to pay off technical debt as you move forward. Don’t stop to pay off technical debt (unless your company has nothing better to do), but allow delivery to slow down to clean things up in process.
One may ask the question: shouldn’t technical debt be avoided in the first place? When a development team is stuck with technical debt, does that imply that something is deficient in their process? The answer is “no.” While it’s possible for companies to fail through accumulation of too much technical debt, it’s also possible for a company to fail by never allowing technical debt. A company that always avoids technical debt is over investing in things they can’t know are true. All companies, big and small, need to explore new territory and efficiently throw out bad product ideas. Doing this requires accumulating technical debt. To learn if users give a crap about what you’re doing, it doesn’t matter how clean the code is. But when your features do achieve traction, it essential to have a principled strategy for cleaning up technical debt as you grow.