No More Technical Debt - Invest in Quality
A Fairy Tale
Once upon a time a software development team went to its manager. “We have quite some Technical Debt in our project, and we should do something about it” the team said. The team showed a graph (fig. 1) to illustrate the Technical Debt of the project. “Technical Debt is related to the quality of the project”, they said. And they showed a breakdown of the individual parts of the Technical Debt - too complex code, code duplication and violations found in static code analysis. “We need to get rid of the Technical Debt” they told the manager.
(Click on the image to enlarge it)
Fig 1: Technical debt as reported by the SonarQube technical debt plug in.
But the manager was left puzzled: What is this Technical Debt about? Should he seriously add another $500.000 to the budget? And for what? This was related to quality - but he wasn’t aware of any issues. The customer had always been happy - what was the team talking about? So the manager and the team had a long discussion.
Actually Technical Debt was introduced as a metaphor to help in these kinds of discussions. The idea is that code with a bad quality is like a financial burden. The total amount of the debt is the effort it would take to clean up the code base. The interest rate is the reduced productivity due to the bad code quality. Management is usually familiar with terms of the financial domain - so it should be easy to talk about software quality using this metaphor.
This story illustrates how Technical Debt as a metaphor fails. It is supposed to help to communicate technical quality to management so it can be acted on and ultimately paid back. However, in reality things are not always that easy. Just because there is Technical Debt does not mean that it has to be paid back. Technical Debt is not even necessarily a bad thing - sometimes it is just part of a compromise to reach a time-to-market goal or other objectives of the project. Sometimes it cannot be avoided - a new technology or a new version of a library renders code written with the old technology a Technical Debt because now things can be done much easier. Also there are no simple laws how Technical Debt should be paid back. In fact there are quite a lot of different ways to pay back Technical Debt or even use it to your advantage .
The Problem with Technical Debt
The main problem with Technical Debt is that it just represents the internal quality of the system. However, the impact of the quality is not clear. In particular the economic impact of the Technical Debt cannot be easily expressed using the metaphor. Technical debt is weird. If no changes to the code are needed, the Technical Debt doesn’t matter at all. However, as soon as the code should be changed, Technical Debt becomes the all important property of the code. So it is perfectly possible that the Technical Debt does not influence the success of the project or the externally visible quality at all.
But if you neglect the Technical Debt of the project, that might backfire at one point: If you need to change code with a lot of Technical Debt, the changes might be prohibitively expensive and therefore not feasible. Developers usually know and fear these kinds of situations - working with code that has a lot of Technical Debt is not just little fun - it is also very risky because bugs might sneak in and estimates might be easily proven wrong.
So while software quality might be very important for the success of a software project, the Technical Debt metaphor is just not enough. It can be used to express the software quality - but it is a lot more important to decide how the software quality should be dealt with than to just recognize what the quality of the project is like.
Invest in Quality: A New Metaphor to the Rescue
So maybe a different metaphor is better suited to decide what should be done concerning the quality of a software system. Technical Debt is just the cost that has to be paid to remedy deficiencies in quality - in the example the total is $500.000. This value by itself is not useful - it does not say what should be done about the problems or how they influence the development of the system. Maybe the Technical Debt should be paid back - maybe that does not make any sense at all.
So a better metaphor might be the Quality Investment. Quality Investment makes it possible to derive a profit from acting on Technical Debt. This enables the active management of code quality in financial terms. So it is easy to decide which quality issues should be resolved and which can be accepted for the time being.
The idea of the Quality Investment is based on SQALE. The SQALE method  is a quality model which defines two types of costs: remediation costs (RC) and non-remediation costs (NRC). The remediation costs are the effort it takes to clean up a certain quality issue in your codebase. In fact, the remediation costs can be seen as the Technical Debt. More interesting is the second group of costs. The non-remediation costs occur when a quality defect is not resolved. So for example the implementation of a new feature might take longer. This additional effort would be the non-remediation cost. In this context the non-remediation costs may look like the interest of technical debt. But in fact these costs should take more into account, e.g. factors like additional risk by not cleaning up the code. In SQALE you can decide whether you want to live with the current state of poor quality and pay the non-remediation cost or if it’s worth to improve the quality and to pay the remediation costs.
Previous implementations of this quality model, such as the SQALE plugin for SonarQube, only support the remediation costs. However, the key for an economically sensible handling of quality and the innovative character of this quality model lies in both types of costs.
If you are improving the quality and are resolving quality issues, the remediation costs are due. However, after the clean-up the team avoids the corresponding non-remediation costs. Thus, it is only worth to improve the quality when the non-remediation costs are greater than the remediation costs. Because only then the Quality Investment yields a profit. This can be easily described by the following profit formula:
Profit = NRC - RC
This gives a guideline if and when quality issues should be resolved - based on sound economic principles.
As already mentioned, the quality of code is only important when it will be changed in the future - because only then the team will be slowed down due to the lower quality. So, the probability that the code will have to be changed must be estimated for a proper investment analysis, in addition to both types of costs. Therefore, the metaphor of the Quality Investment can be implemented by three estimates. Let us look at an example to gain more insight into this.
Suppose we consider a system that consists of three components: customer, order and invoicing. The customer management is very old and is no longer being actively developed. Therefore, this component is not suitable for a Quality Investment: The remediation costs only occur if the code is changed - so in this case they will occur with a probability of 0%. So any paid remediation costs will end in a loss.
However, we know that in the next iteration extensive changes to the ordering process are made. We also know from experience that changes in the order management component led to some changes to the invoicing. Rough estimates like these are usually sufficient, and it is also easier to agree on such a value. Experience teaches that detailed estimates mostly just pretend precision.
In a further step, the quality defects in these two components - the order and invoicing - have to be estimated. The test coverage in the order management is quite low, and the code in customer management is rather complex i.e. method and classes with a high number of lines of code and high cyclomatic complexity. For all the points that stand out to us, we estimate the remediation and non-remediation costs. The estimates for the non-remediation costs should also take the change probability of the component into account. In the next iterations an estimated 20 days would be invested in the order management if the code quality stays the same - and an estimated 13 days if the test coverage is improved. The non-remediation cost therefore is 7 days. It is very high because the quality is so bad there, but also because extensive changes must be made:
- Order management: low test coverage, RC: 5d, NRC: 7d
- Invoicing: High complexity, RC: 5d NRC: 4d
These estimates state that a Quality Investment in the order component results in a profit of 2 days (= 7d down to 5d). In contrast, no profit can be expected for the invoicing - it is even a loss. It is thus clear that an investment in the current ordering system is useful because improving the test coverage promises a profit - according to estimates of the team. For the invoicing the situation is not that clear. Right now an investment in the quality gains no profit. However, it is quite likely that the invoicing component will be changed in the next few iterations, too. Then you would get a profit from the investment in the quality of the invoicing component.
With the given estimates and the calculated profit it is also possible to derive the return of investment (RoI) for each Quality Investment. The RoI indicates how much profit is generated in relation to the costs. For this, the profit must be divided by the remediation costs. For the Quality Investment in the order component the RoI is about 40% (= 2d/5d ). With these financial terms you can communicate the benefit of better quality to your manager who is usually looking for chances to get a high RoI. Of course these numbers are estimates - like almost everything else in software development. However, they show that the team is not just looking to improve the quality for its own sake but rather because of economic reasoning.
The metaphor of Quality Investment allows a different kind of discussion with management. Rather than costs for the Technical Debt, saved time and effort can be communicated to the manager. For the manager, this means a win-win-situation: budget will be saved, and the developers are happy because they can improve the code quality. Similarly, the manager may consider whether the investment is appropriate or a quick & dirty solution is sufficient or even necessary because of the time-to-market.
Ultimately, the Quality Investment is a comparison of different estimates: what is economically the best decision? However, it begs the question of why the idea of an investment is not already being used much more in software development.
Another Fairy Tale
So let’s retell the Fairy Tale from the beginning - this time with Quality Investments:
Once upon a time a software development team went to its manager. “We believe we found a way to improve the development” they said. “We did some estimations. Originally we came up with pretty high numbers for all the changes we need to do for the order process in the next iterations. However, if we invest 5 days in improving the test coverage in the order management, we estimate that we will save 7 days of effort in the next iterations - so we will have 2 days less effort.” “Great”, the manager said, “let’s do that! Thanks for the valuable input!” So the team could finally improve the quality of this component that everyone was concerned about. “So here is another one.” the team said. “If we invest another 5 days in the quality of the invoicing we think we will be able to save 4 days. Even though this is a loss, we believe in the next iterations we will get a profit out of this”. The manager replied: “OK. However, in this iteration we really need to roll out as many features as possible and the two additional days are really handy. The customer is currently not very happy, and I need to impress him - otherwise there will probably be no iteration after the next...” So they went on, improved the quality in the order management and lived happily ever after.
This illustrates why Quality Investments are so handy as a metaphor: The profit of individual decisions concerning quality can be estimated. And it is also easily possible to prioritize investments in quality against other concerns such as implementing new features. All of this would not be possible without this metaphor. Of course it is only possible if the team has a history of good estimates. But even if this is not the case, it helps to think in these terms because they help to come to more economic decisions.
There is also tooling support to support Quality Investment called CodeQ Invest . It is a web application that provides automatically calculated probabilities for the code change on different levels - from individual classes up to the root package. The source control system is used to compute suitable numbers. The starting point is the idea that code which was changed quite often in the past is more likely to be changed in the future than untouched code. You can define the number of days which should be taken into account for this calculation. Each commit that happened during these days is evaluated - per changed file the proportion of changed code is calculated. Furthermore, you can choose between different methods to evaluate code changes in the past:
- equally weighting all commits during the last X days
- exponentially weighting all commits during the last X days (younger code changes count more)
- equally weighting the last X commits
Beside this automatic calculation of change probabilities, you can also use manual estimates for the change probability of individual parts of the code. The calculated probabilities are especially useful if the system is in maintenance mode i.e. no new features are added. Also it gives interesting insight in the code base and the hot spots which might be in the code. Manual estimates are very well suited if new features are developed - in particular if pieces of the code must be changed that haven’t been touched in a while.
CodeQ Invest also has many other features. It calculates the best possible investments in your codebase. You provide a budget i.e. a certain number of hours that should be invested in the quality of the system and CodeQ Invest suggests what should be improved in which parts of the code. The team has to define a quality profile for that. This profile defines the code quality from the point of view of this specific team. A different team probably comes up with a different quality profile. The profile consist of many quality requirements. Each requirement states a measurable aspect of code quality. At the current state of development, CodeQ Invest allows you to express thresholds for different metrics. They are measurable by SonarQube (formerly Sonar) , a very popular code quality management tool which is used to get the metrics for the analyzed code. Furthermore, for each quality requirement remediation and non-remediation costs must be estimated by the team. So, the team has to estimate the costs only on very low level e.g. how long does it take to improve the test coverage of 100 lines of code by 10%? What is the impact on implementing a story based on code that has this test coverage? The aggregation to higher levels of abstraction is done for you by the tool. How this looks like is shown in figure 2.
CodeQ Invest is only a tool to support you in pushing the new metaphor and new way to deal with code quality further. At the bottom it is all about estimates. They can be either done in the traditional way i.e. estimating stories, quality improvements and the impact of Quality Investments on the effort for specific stories. Or you can use CodeQ Invest and configure it with numbers for the impact of certain quality characteristics as you see it. CodeQ Invest will take those basic numbers and come up with suggestions for investment plans.
(Click on the image to enlarge it)
Fig 2: Project view of CodeQ Invest. It displays a zoomable tree map with investment opportunities in your codebase. On the right side you can see the RoI distribution for several budgets (e.g. 16 or 32 hours) and a generated quality investment plan on the base of a given investment from the RoI distribution.
So while Technical Debt helps to communicate the quality of a software system, it is not very helpful when it comes to figuring out what to do about the quality. This can lead to many problems e.g. code with bad quality that cannot be maintained. At the end the main concern is where the quality of a system should be improved - and where it is OK to just live with the current level of quality. This is where Quality Investments helps: Each improvement is judged by its economic outcome i.e. will it be cheaper to just leave the code as is or to invest in quality? This gives a good guideline to where quality should be improved and how the work on the quality of the code should be prioritized against implementing new features.
About the Authors
Eberhard Wolff is a freelance architect and consultant. He is also head of the Technology Advisory Board of the adesso AG. His interests include agile techniques and modern software architecture.
Felix Müller works as an IT consultant at codecentric AG in Berlin. He is a passionate software developer. His main interests in this field are web development, test automation, continuous delivery, code quality management and agile practices.
Brittle software is software that requires more time to make changes to in the future. Unfortunately, changes to software naturally tend to make the software more brittle. However, with focused effort brittleness can be reduced and malleability (the speed with which changes can be made to software) can be maintained.
This is why brittleness increases particularly when changes are made within excessive time constraints (disallowing for brittleness to be addressed). Furthermore, as brittleness compounds, the time cost of changes increases exponentially.
Good vs. bad debt
One analogy I like to use is financial debt (for realz). "Good debt" is taken to enable an asset, i.e., profit generation (e.g., start a business, or passive income from real estate), while "bad debt" is sunk in a liability (e.g., buying a car, or house).
Hence, not all debt is bad - choose wisely.
Re: Good vs. bad debt
thanks a lot for you feedback!
I think it is interesting that software development is considered a cost center - while it should really provide value. Actually I believe Quality Investments should really be considered in terms of the additional value IT can provide due to such investements.
Concerning bad vs. good technical debt: I think there is hardly such a thing as "deliberate technical debt". I cannot imagine a developer thinking "Wow, I am going to write low quality code now." At the end the developer will probably have to maintain it. So I think what is usually called "deliberate technical debt" is really "messing up because of time pressure". So it's not necessarily a decision about Technical Debt - it is probably more a decision about the schedule. For that reason I am not sure whether you are managing Technical Debt in that case at all.
Thanks again for the feedback!
Re: Good vs. bad debt
In a startup environment (in which I currently find myself), we are continuously making conscious decisions about what Technical Debt is okay to keep, or even introduce, for the sake of value delivery (& commensurate profit, marketshare, etc.). But I have seen such tradeoffs made with varying success at larger orgs with legacy code as well.
BTW, thank you for the article. My interest has been piqued and I am starting to look more deeply into SQALE & associated tooling.