Since installing Sonar over a year ago, we’ve been working to reduce our technical debt. In some of our applications, which have been around for nigh on a decade, we have accumulated huge amounts of technical debt. I don’t hold much faith in the numbers produced by Sonar in absolute terms, but it is encouraging to see the numbers go down little by little.
Our product management team seems to have grabbed onto the notion of technical debt. Being from a financial institution they even get the notion that bad code isn’t so much a debt as an un-hedged call option, but they also recognize that it’s much easier to explain (and say) “technical debt” than “technical unhedged call option.” They get this idea, and like it, but the natural question they should be asking is, “How much interest should they expect to pay should we take on some amount of technical debt?”
In the real world, debt upon which we pay no interest is like free money: you could take that loan and invest it in a sure-win investment, and repay your debt later, pocketing whatever growth you were able to get from the investment. It’s the same with code: technical debt on which you pay no interest was probably incurred to get the code out faster, leaving budget and time for other money-making features.
How do we calculate interest, then? The interest is a measure of how much longer it takes to maintain the code than it would if the code were idealized. If the debt itself, the principal as it were, corresponds to the amount of time it would take to rectify the bad code, the interest is only slightly related to the principal. And thus you see, product management’s question is difficult to answer.
Probably the easiest technical debt and interest to understand is that from duplicate code. The principal for duplicate code is the time it would take to extract a method and replace both duplicates with a call to the method. The interest is the time it takes to determine that duplicate code exists and replicate and test the fix in both places. The tough part is determining that the duplicate code exists, and this may not happen until testing or even production. Of course, if we never have to change the duplicate code, then there is no effort for fixing it, and so, in that case, the interest is zero.
So, I propose that the technical interest is something like
Technical Interest = Cost of Maintaining Bad Code * Probability that Maintenance is Required
You quickly realize then that it’s not enough to talk about the total debt in the system; indeed, it’s useless to talk about the total debt as some of it is a zero-interest, no down-payment type of loan. What is much more interesting is to talk about the total interest payments being made on the system, and for that, you really need to decompose the source code into modules and analyze which modules incur the most change.
It’s also useful to look at the different types of debt and decide which of them are incurring the most interest. Duplicate code in a quickly changing codebase, for example, is probably incurring more interest than even an empty catch block in the same codebase. However, they both take about the same amount of time to fix. Which should you fix first? Because the interest on technical debt compounds, you should always pay off the high-interest loan first.