Anyone whose professional life has intersected with the technical debt metaphor knows its power: the simple proposition that such a thing exists opens up a new channel of communication among groups (IT and application developers, designers, biz dev) that famously have trouble communicating about technical decisions. Not everyone understands test cases, aging platforms, crufty code bases, or security loopholes, but everyone understands debt (needless to say, most everyone has personal debt, and a sizable proportion of the news media conversation concerns debts, mortgages, and deficits).
Technical debt is first and foremost a metaphor. It describes a real phenomenon, but it does not map neatly onto the concept of financial debt. Financial debt is always quantifiable in its current cost, as well as in its behavior over time.
For instance, we can solve for A, where A is monthly payment amount, P is principal, r is interest rate, and m is months to pay:
A = P (r / 12) / (1 (1 + r / 12) m)
Imagine, if we could only calculate our technical debt burden in a spreadsheet!
With the traction that the technical debt metaphor has enjoyed in recent years, the IT industry has started to develop tools and services around the identification and minimization of debt. It greatly aids the business case to be able to propose a monetization or other quantification of debt, so we’ve seen everything from quasi-academic to food-based for how to do so.
And given that there is a real cost here, however occulted it may be, technical debt is a crucial factor in very real-world decisions. Acquiring a company with a desirable technology, for instance, hinges on the long-term prospects of that technology. And its prospects are hindered, sometimes fatally, by its technical debt. Even if the purchase is a play for technical talent, the valuation of that talent must be calculated in part by the debt they built (or, better, didn’t build) into their product. Either way, the decision must include some valuation of the health of the acquired technology. (See this post by Chris Dixon for a wonderfully concise discussion of the valuation logic.)
Similarly, an organization buying into a platform needs not just to lay out cash, but to hitch its IT wagon to an outside entity. If the platform is laden with hidden debt, it will be prohibitive to maintain and upgrade, and the buyer may end up with an intractable commitment to an abandoned technology owned by a failed company.
Despite the sometimes critical need to quantify debt, however, it is crucial to recognize that technical debt is not always quantifiable—not in all its forms, and not always in the way that we could enumerate as integers in a spreadsheet. Just as important, we must acknowledge that this doesn’t point to an immaturity in the development of the concept, but rather a fundamental difference between technical and financial debt. Ward Cunningham, among others, has recently acknowledged this conceptual gap.
Financial debt has but one form: Money owed.
A partial list of the many varieties of technical debt:
- Lack of test coverage
- Muddy or overly rigid content type definitions
- Hardcoded values
- Misused APIs
- Redundant code
- Inappropriate or misunderstood design patterns
- Brittle, or missing, or nonescalating error handling
- Unscalable software architectural design
- Foundational commitment to an abandoned platform
- Missing or inaccurate comments and documentation
- “Black box” components
- Third-party code that’s fallen far behind its public stable release
- Overly long classes, functions, control structures (cyclomatic complexity)
- Clashing programming or software architectural styles within a single application
- Multiple or obscure configuration file languages
- Hardwired reliance on a specific platform or product (e.g., MySQL, Solaris, Apache httpd)
To the extent that some of these are almost purely qualitative, they are categorically impossible to fix with an exact price. The only possible way of estimating would be in developer hours required to address, and that is as subject to misestimation as any other relatively complex task.
It is unfortunate but undeniable that many attempts at providing a cost analysis of technical debt are too generic or too narrowly focused to be helpful. The claim that, for instance, static code analysis can provide a usable quantification of technical debt implicitly denies the existence of many of the types of debt listed above. How could we limit our understanding of debt to this narrow view of code quality? The qualification that static analysis attempts to identify just that debt which is both significantly harmful and based in code begs the question of why this slice of a valuation, given its limits, should be a helpful number to calculate in the first place. Given the inability of programming languages to capture some crucial technical aspects of an application (e.g., architectural style), we should be suspicious of analyses that start and end with the bare code.
Similarly, it is tempting to get lost in the details of a calculation algorithm, and ignoring the other facets of the situation that may themselves constitute equally or more significant sources of debt. Some seem skewed towards valuation as a scare tactic. Perhaps we should be scared: if every line of code carries an implicit cost as debt, the only solution may be to unplug and run for the hills.
Any productive consideration of technical debt must start with enumerating its many causes and manifestations, and then choosing a subset to focus on—while acknowledging that it may be necessary subsequently to widen the focus to achieve a realistic evaluation.