Technical debt (also known as design debt or code
debt) is a concept in software development that reflects the implied cost
of additional rework caused by choosing an easy solution now instead of using a
better approach that would take longer.
Technical debt can be compared to monetary debt. If technical debt is not repaid, it can accumulate 'interest', making it harder to implement changes later on. Unaddressed technical debt increases software entropy. Technical debt is not necessarily a bad thing, and sometimes (e.g., as a proof-of-concept) technical debt is required to move projects forward. On the other hand, some experts claim that the "technical debt" metaphor tends to minimize the impact, which results in insufficient prioritization of the necessary work to correct it.
As a change is started on a codebase, there is often the need to make other coordinated changes at the same time in other parts of the codebase or documentation. Required changes that are not completed are considered debt that must be paid at some point in the future. Just like financial debt, these uncompleted changes incur interest on top of interest, making it cumbersome to build a project. Although the term is used in software development primarily, it can also be applied to other professions.
Common causes of technical debt include (a combination of):
"Interest payments" are caused by both the necessary local maintenance and the absence of maintenance by other users of the project. Ongoing development in the upstream project can increase the cost of "paying off the debt" in the future. One pays off the debt by simply completing the uncompleted work.
The buildup of technical debt is a major cause for projects to miss deadlines. It is difficult to estimate exactly how much work is necessary to pay off the debt. For each change that is initiated, an uncertain amount of uncompleted work is committed to the project. The deadline is missed when the project realizes that there is more uncompleted work (debt) than there is time to complete it in. To have predictable release schedules, a development team should limit the amount of work in progress in order to keep the amount of uncompleted work (or debt) small at all times.
If enough work is completed on a project to not present a barrier to submission, then a project will be released which still carries a substantial amount of technical debt. If this software reaches production, then the risks of implementing any future refactors which might address the technical debt increase dramatically. Modifying production code carries the risk of outages, actual financial losses and possibly legal repercussions if contracts involve service-level agreements (SLA ).
For this reason we can view the carrying of technical debt to production almost
as if it were an increase in interest rate and the only time this
decreases is when deployments are turned down and retired.
"As an evolving program is continually changed, its complexity, reflecting deteriorating structure, increases unless work is done to maintain or reduce it."
While Manny Lehman's Law already indicated that evolving programs continually add to their complexity and deteriorating structure unless work is done to maintain them, Ward Cunningham first drew the comparison between technical complexity and debt in a 1992 experience report:
"Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite... The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise."
In his 2004 text, Refactoring to Patterns, Joshua Kerievsky presents a comparable argument concerning the costs associated with architectural negligence, which he describes as "design debt".
Activities that might be postponed include documentation, writing tests, attending to TODO comments and tackling compiler and static code analysis warnings. Other instances of technical debt include knowledge that isn't shared around the organization and code that is too confusing to be modified easily.
Grady Booch compares how evolving cities is similar to evolving software-intensive systems and how lack of refactoring can lead to technical debt.
"The concept of technical debt is central to understanding the forces that weigh upon systems, for it often explains where, how, and why a system is stressed. In cities, repairs on infrastructure are often delayed and incremental changes are made rather than bold ones. So it is again in software-intensive systems. Users suffer the consequences of capricious complexity, delayed improvements, and insufficient incremental change; the developers who evolve such systems suffer the slings and arrows of never being able to write quality code because they are always trying to catch up."
In open source software, postponing sending local changes to the upstream project is a technical debt.
Technical debt can be compared to monetary debt. If technical debt is not repaid, it can accumulate 'interest', making it harder to implement changes later on. Unaddressed technical debt increases software entropy. Technical debt is not necessarily a bad thing, and sometimes (e.g., as a proof-of-concept) technical debt is required to move projects forward. On the other hand, some experts claim that the "technical debt" metaphor tends to minimize the impact, which results in insufficient prioritization of the necessary work to correct it.
As a change is started on a codebase, there is often the need to make other coordinated changes at the same time in other parts of the codebase or documentation. Required changes that are not completed are considered debt that must be paid at some point in the future. Just like financial debt, these uncompleted changes incur interest on top of interest, making it cumbersome to build a project. Although the term is used in software development primarily, it can also be applied to other professions.
Causes
Common causes of technical debt include (a combination of):
- Insufficient up-front definition, where requirements are still being
defined during development, development starts before any design takes
place. This is done to save time but often has to be reworked later.
- Business pressures, where the business considers getting
something released sooner before all of the necessary changes are
complete, builds up technical debt comprising those uncompleted changes.
- Lack of process or understanding, where businesses are blind to the
concept of technical debt, and make decisions without considering the
implications.
- Tightly-coupled components, where functions are not modular,
the software is not flexible enough to adapt to changes in business needs.
- Lack of a test suite, which encourages quick and risky band-aids
to fix bugs.
- Lack of documentation, where code is created without
necessary supporting documentation. The work to create any supporting
documentation represents a debt that must be paid.
- Lack of collaboration, where knowledge isn't shared around
the organization and business efficiency suffers, or junior developers are
not properly mentored.
- Parallel development on two or more branches accrues technical
debt because of the work required to merge the changes into a single
source base. The more changes that are done in isolation, the more debt is
piled up.
- Delayed refactoring – As the requirements for a project
evolve, it may become clear that parts of the code have become inefficient
or difficult to edit and must be refactored in order to support future
requirements. The longer that refactoring is delayed, and the more code is
added, the bigger the debt.
- Lack of alignment to standards, where industry standard features,
frameworks, technologies are ignored. Eventually, integration with
standards will come, doing sooner will cost less (similar to 'delayed
refactoring').
- Lack of knowledge, when the developer simply doesn't know how
to write elegant code.
- Lack of ownership, when outsourced software efforts result in
in-house engineering being required to refactor or rewrite outsourced
code.
- Poor technological leadership where poorly thought out commands
handed down the chain of command increases the technical debt rather than
reduce it.
- Last minute specification changes; these have potential to percolate
throughout a project but no time or budget to see them through with
documentation and checks.
Consequences of Technical Debt
"Interest payments" are caused by both the necessary local maintenance and the absence of maintenance by other users of the project. Ongoing development in the upstream project can increase the cost of "paying off the debt" in the future. One pays off the debt by simply completing the uncompleted work.
The buildup of technical debt is a major cause for projects to miss deadlines. It is difficult to estimate exactly how much work is necessary to pay off the debt. For each change that is initiated, an uncertain amount of uncompleted work is committed to the project. The deadline is missed when the project realizes that there is more uncompleted work (debt) than there is time to complete it in. To have predictable release schedules, a development team should limit the amount of work in progress in order to keep the amount of uncompleted work (or debt) small at all times.
If enough work is completed on a project to not present a barrier to submission, then a project will be released which still carries a substantial amount of technical debt. If this software reaches production, then the risks of implementing any future refactors which might address the technical debt increase dramatically. Modifying production code carries the risk of outages, actual financial losses and possibly legal repercussions if contracts involve service-level agreements (
"As an evolving program is continually changed, its complexity, reflecting deteriorating structure, increases unless work is done to maintain or reduce it."
— Meir Manny Lehman, 1980
While Manny Lehman's Law already indicated that evolving programs continually add to their complexity and deteriorating structure unless work is done to maintain them, Ward Cunningham first drew the comparison between technical complexity and debt in a 1992 experience report:
"Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite... The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise."
— Ward Cunningham, 1992
In his 2004 text, Refactoring to Patterns, Joshua Kerievsky presents a comparable argument concerning the costs associated with architectural negligence, which he describes as "design debt".
Activities that might be postponed include documentation, writing tests, attending to TODO comments and tackling compiler and static code analysis warnings. Other instances of technical debt include knowledge that isn't shared around the organization and code that is too confusing to be modified easily.
Grady Booch compares how evolving cities is similar to evolving software-intensive systems and how lack of refactoring can lead to technical debt.
"The concept of technical debt is central to understanding the forces that weigh upon systems, for it often explains where, how, and why a system is stressed. In cities, repairs on infrastructure are often delayed and incremental changes are made rather than bold ones. So it is again in software-intensive systems. Users suffer the consequences of capricious complexity, delayed improvements, and insufficient incremental change; the developers who evolve such systems suffer the slings and arrows of never being able to write quality code because they are always trying to catch up."
— Grady Booch, 2014
In open source software, postponing sending local changes to the upstream project is a technical debt.
Related Topics
- Code smell (symptoms of inferior code quality
that can contribute to technical debt)
- Big ball of mud
- Software rot
- Bus factor
- Escalation of commitment
- Software entropy
- SQALE
- Sunk costs
- TODO, FIXME, XXX
No comments:
Post a Comment