What is it & how does it affect software engineering management?
The ‘Golden Triangle’ of project management
The ‘golden triangle’ of project management uses the following constraints:
The rule is: you can pick any two of three; you can’t have them all.
When it comes to software development projects, it’s not uncommon to have a fixed time to market and budget, which means that, under pressure, the constraint that’s affected is quality.
Commonly, when the project management refers to ‘quality’ it implicitly means Intrinsic Quality.
Intrinsic quality and technical debt
Intrinsic Quality is the inherent ‘goodness’ of a system. That is, not what the product is/does, but how well it has been designed and constructed. If you like, Intrinsic quality is a measure of the engineering rigour that has been put into the product.
In the case of software-oriented products Intrinsic quality tends to manifest itself in architectural robustness and resilience to change.
Intrinsic quality is closely allied to the idea of Technical Debt.
Technical debt is a term created by Ward Cunningham in 1992, which describes “the obligation that a software organisation incurs when it chooses a design or construction approach that’s expedient in the short-term but that increases complexity and is more costly in the long-term.”(1)
A company will put effort into the design and architecture of their systems to give them greater flexibility in the future. Engineering rigour, and designing for change and maintainability reduces (but cannot complete eliminate, unfortunately) the impact of technical debt. That is, the higher the Intrinsic quality of a product, the less it will cost to maintain, modify and extend it during its life.
Note Intrinsic quality benefits the development organisation, and is largely invisible to the customer; thus very few customers are willing to pay for such work. Intrinsic quality is therefore an upfront cost to the development organisation, which has to be balanced against the reduced future costs of product maintenance.
If time-to-market and cost are fixed constraints in a project it is compelling to sacrifice the costs of engineering intrinsic quality.
Sacrificing intrinsic quality for short-term expediency must come at a (future) price. There’s no such thing as a free lunch! The challenge becomes calculating what the future cost will be.
The cost of technical debt
You can think of Technical Debt as a compound interest charge: it’s not only the length of time the ‘debt’ is held that’s a factor, but also the ‘interest rate’. This ‘interest rate’ isn’t fixed; and varies depending on where the compromises are made.
Technical debt affects all aspects of the software engineering process: including requirements and deployment to the user base, writing the code and the tools used to analyse code and modify it.(2)
Problem domain technical debts – that is, customer-facing omissions, compromises, failures, etc. – will (obviously) have the highest ‘interest rates’.
Architectural debts will have the largest effect on product extensibility, flexibility, maintainability, and so incur a high ‘interest rate’.
Coding issues – semantic errors, unit test failures, algorithmic inefficiencies – are the easiest to measure and categorise, so these areas tend to get the most attention. However, the ‘interest rate’ of such technical debts is relatively low, meaning issues can persist for long periods without significant impact on the overall technical debt of the product.
However, it’s not just the quality aspects or features that we know have been compromised in order to meet the cost/time constraints that must be counted as technical debt, The ‘unknown unknowns’ – that is, the things we don’t know we don’t know (made famous by former Secretary of Defence Donald Rumsfeld) – becomes a factor here too. The more unknown-unknowns there are in a domain, the easier it is to not factor them in. As a result, anything not-factored-in early enough also becomes a technical debt.
Take the following statistics by Tom de Marco (3). The chart shows the root cause of bugs in a typical software project
A couple of points worth noting here:
The smallest number of bugs can be traced to coding errors. Technical debts in this area have the lowest ‘interest rates’. Contrastingly, the largest number of bugs can be traced to requirements issues. These problem domain issues have the largest ‘interest rates’ for technical debt. Thus a typical software project accumulates its debts at the very highest rates of interest!
Evidence suggests that as developers move away from their ‘core’ skill – that is, the one they practice the most (writing code), the more unknown unknowns they are subject to. The chart then is also a pretty good indicator of ‘unknown unknowns’ in a project. The more ‘unknown unknowns’ the more likely it is the developer will make mistakes (and introduce bugs).
How much is my technical debt?
In 2012, researchers conservatively estimated that for every 100 KLOC (thousand of lines of code), an average software application had approximately US$361,000 of technical debt – that is, the cost to eliminate the structural-quality problems that seriously threatened the application’s business viability. (4)
5 steps to managing technical debt
1. Identify the technical debt – for example, applying the Swiss Cheese model to your system verification and validation (see below)
2. Measure the technical debt in terms of benefit and cost – Thinking of technical debt as compound interest, then the benefit is the amount of money you save by paying off the ‘loan’ early. The tricky bit is establishing what the ‘interest rate’ is for your organisation.
3. Prioritise the technical debt – identify the items that identify the items that have the highest payoff and repay them first. Of course, you can only prioritise technical debts that you can see. The dichotomy here is that the aspects most likely to have the highest technical debts are the ones you can’t currently see (the unknown unknowns)!
4. Repay the technical debt through refactoring – you can only refactor code successfully if you have adequate testing in place. That is, every restructuring change you make can have no impact on the (measurable) functionality of the system. Establishing and automating (where possible) verification and validation regimes for your project is an intrinsic quality exercise. And remember: the sacrificial lamb of project management is intrinsic quality! Companies with rampant technical debt tend to lack these regimes, thus exacerbating the problem by raising the ‘interest rate’ of their technical debt.
5. Monitor items that aren’t repaid – because their cost or value might change over time (certain technical-debt items can escalate to the point of becoming unmanageable). Once again, we can only monitor things we know are (currently) wrong. It is difficult to monitor unknown unknowns!
The Swiss Cheese Model and Technical Debt
There is no one, perfect, way to identify technical debts. Using multiple, independent techniques (each playing to their own strengths) is far more effective.
The “Swiss Cheese” approach to identifying Technical Debt uses multiple techniques, each with a different focus. The techniques are applied with the clear knowledge that no technique is perfect (nor should it be) but the flaws in any one technique do not overlap (much!) with the flaws of another layer.
- The Static Analysis layer in the model identifies ambiguity and mistakes in codification. These are things that are difficult for engineers to spot, but easy to fix. Static Analysis tools are readily available and have a low cost to apply regularly on a code base. However, Static Analysis cannot identify incorrect algorithms or missing code and the debts it resolves are relatively tiny.
- The Testing layer verifies system correctness. Since it focuses on failures (deviations from customer specification), technical debts are visible and obvious to the organisation.
- The Review layer validates requirements and designs. It asks the questions: “Are we solving the right problem?”; “Are we solving it in the right way?” As review is a human-centric activity, tools typically help very little, beyond some metrics such as: cyclomatic complexity; or compile-time coupling, for example. As a result, the technical debts established by reviews are generally larger-scale, more ‘expensive’ and require far more effort (and money) to resolve.
Understanding Technical Debt is a critical part of software development project management. Sacrificing project intrinsic quality to expediate project delivery has to be very carefully balanced against the long-term costs of maintenance, extensibility, flexibility and re-use. Since the lifetime of a system could potentially extend into decades the costs of not removing Technical Debts could become untenable to the viability of the system.
Code-level restructuring / refactoring, whilst always beneficial, have the smallest beneficial impact. The higher ‘interest rates’ of Technical Debts associated with architectural problems typically far out-shadows the benefits gained from code-level fixes.
As a result, in order to be effective, engineers should be trained in software architecture, software design and even requirements analysis (5). All these topics are far more sophisticated that writing code and it takes time and effort to develop appropriate skills.
-  http://www.construx.com/10x_Software_Development/Technical_Debt/
-  Reducing Friction in Software Development – Paris Avgeriou, University of Groningen, Philippe Kruchten, University of British Columbia, Robert L. Nord and Ipek Ozkaya, Software Engineering Institute, Carolyn Seaman, University of Maryland, Baltimore County. Published by the IEEE Computer Society, 2016. https://ieeexplore.ieee.org/document/7367977/
-  Structured Analysis and System Specification, De Marco T, Yourdon Press ISBN 0-138-54380-1, 1978
-  B. Curtis, J. Sappidi, and A. Szynkarski, “Estimating the Principal of an Application’s Technical Debt,” IEEE Software, vol. 29, no. 6, 2012, pp. 34–42.
-  A. Martini, J. Bosch, and M. Chaudron, “Investigating Architectural Technical Debt Accumulation and Refactoring over Time: A Multiple-Case Study,” Information and Software Technology, Nov. 2015, pp. 237—253.
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.
He specialises in C++, UML, software modelling, Systems Engineering and process development.