Let’s talk about the elephant in the room (not Apache Hadoop) – technical debt.
From practically the first line of code every team begins accruing technical debt – some faster than others – in the pursuit of producing a product. Technical debt is so prevalent that there’s an international conference focused solely on the topic – techdebtconf.org
What Is Technical Debt?
Before we dive into strategies for managing technical debt, we should define what it is.
You can also define technical debt according to what it is NOT. This great Plutora article summarizes some of the misconceptions regarding technical debt. It seems that some confuse technical debt with bugs and with writing bad code (with full intention to adjust it later). It is neither.
So what is it? Let’s start with the simple definition, by Wikipedia: “Technical debt is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer.”
In his article, Martin Fowler addresses another definition; “software systems are prone to the build up of cruft – deficiencies in internal quality that make it harder than it would ideally be to modify and extend the system further. Technical Debt is a metaphor, coined by Ward Cunningham, that frames how to think about dealing with this cruft, thinking of it as financial debt. The extra effort that it takes to add new features is the interest paid on the debt.”
Whether you consider the Wikipedia definition, or the metaphor by Ward Cunningham, the picture is quite clear.
Think of it this way: debt is something borrowed against something owed. When we focus on debt in technology, it is most common to be referring to achieving some milestone, such as a software release, as the borrowed and deferred rework, such as writing code to add a feature that was skipped, as the owed. Technical debt isn’t just about writing code properly (although code complexity is one of the main types of technical debt). Debt can also be incurred from configuration gaps, definitions or requirements gaps, low test coverage, lack of documentation, old legacy technology (may it be libraries, frameworks, and even programming languages), and more. This DZone article explains some of these types thoroughly.
Whatever the reason might be, or the type of technical debt, just like monetary debt, technical debt can accrue interest over time and become increasingly expensive to repay.
Some Numbers to Get Us Going
Is technical debt rare? Not by a long shot. In fact, it is so common that according to McKinsey survey “10 to 20 percent of the technology budget dedicated to new products is diverted to resolving issues related to tech debt.”
If you look at the time factor, it’s still very common. According to Stripe, “engineers spend 33% of their time dealing with technical debt”, which can amount to around 13.4 hours a week.
IT leaders paint a gloomy picture as well. An OutSystems report suggests that “a majority (69%) of IT leaders say technical debt poses a fundamental limit on their ability to innovate, along with 61% saying it drags on their company’s performance and 64% agreeing it will continue to have a major impact in the future.”
So yep, common. Now let’s review the damage, or the potential (depending on how you look at it).
If we’ll get back to Stripe, they estimate technical debt has a $3 trillion impact on global GDP.
And if we want to be more specific, according to a 2021 CodeScene report – the average organization loses 23-42% of development time, due to technical debt. This means that an average organization pays for 100 developers but only achieves the output of 75 developers. Inversely, reducing technical debt in an organization could return an effective 25% or greater increase in output, after paying the investment in closing the technical debt.
Gartner’s research also points out the potential: “through 2023, Infrastructure and operations (I&O) leaders who actively manage and reduce technical debt will achieve at least 50% faster service delivery times to the business.”
The question of ROI (Return on Investment) is tricky, as the amount of investment needed for each project, to close technical debt, and the actual return, are hard to calculate.
And still, if you remember to pay it back later, as with any other debt, technical debt is not necessarily a bad thing as it allows achieving short-term goals, such as faster releases of a feature. By doing so, you can receive customer feedback more quickly, which is very valuable. Just keep in mind that technical debt grows, so it is important to address sooner rather than later.
Measuring Technical Debt
I could go on explaining why you should measure technical debt in the first place. But let’s just sum it up this way: as with other aspects, measurement is the bottom line and therefore is very important. It allows you to understand what to fix and where to focus. The famous quote by Peter Drucker; “If you can’t measure it, you can’t improve it.” is not lost in this discussion.
However, measuring technical debt could be a challenge. Although there’s the Technical Debt Ratio (which I’ll discuss shortly), one might argue there isn’t just one metric or formula. To some extent, measurement of technical debt is unique to each organization as each manages risks and priorities differently. For example, some organizations take bug count, the code to be refactored, code complexity, coding rules violations as possible metrics, while others don’t.
Still, one common baseline for debt measurement is called the Technical Debt Ratio (TDR):
TDR = (Cost of Remediation / Cost of Development) * 100%
Remediation Cost (RC) is the cost associated with building a software product. Generally, when calculating TDR this is already fixed because the software product has been developed and accrued technical debt. When calculating TDR during an active project, however, this can be a combination of the fixed cost – hours already spent – and estimated cost – remaining hours allocated for the project. For many projects, this can be thought of as the sunk cost.
Development Cost (DC) is a bit more accessible – the time required to develop code to address the debt. The value of DC can vary by the specifics of the debt, generally a measure of code volume, and by the resources assigned to the work, generally a factor of the number of developers. DC can be restated as the Cost to develop 1 line of code * Number of lines of code
How Can DevOps Help?
Although a lot of voices out there claim that DevOps is not the cure for technical debt, there are things DevOps does help with in relation to technical debt. True, an organization with a DevOps culture isn’t inherently immune to technical debt nor accruing interest on debt. However, DevOps introduces some issues that sure do help.
DevOps (and CI/CD) is nothing if not automation. When you automate some of the time-consuming tasks or the tasks that are more error-prone than others, you can make use of that saved time in repaying technical debt. Automation embodied in the CI/CD process, such as automated testing and automated builds, also helps in identifying technical debt earlier, which in turn helps with continuous debt repayment. And what about code quality? Automation enforces quality standards that also assist in reducing technical debt.
Communication is another aspect of DevOps that has the potential to help. Many DevOps organizations include a retrospective task in their operational calendar, such as at the conclusion of a sprint for Agile. This can provide an effective platform for cataloging and tracking technical debt that has been incurred as well as communicating to other stakeholder teams when there may be an impact from debt, at the outset, or to prioritize inherited debt, such as when a blocking capability has been delivered. Open communication – a hallmark of healthy DevOps organizations – is a crucial tool for managing technical debt over long periods.
On the topic of communication – now from the technical side of communication – the way that components of the application stack communicate with each other can also be an important factor in addressing technical debt with DevOps. Pursuing a model of services that are centered around communicating via a series of application programming interfaces (API) can help DevOps teams to both improve the visibility of application expectations and increase the durability of those communications. Thus, by implementing an API, any team that later interacts with the service in question has a clearly defined set of expectations to consume in communicating with the service. Some organizations also choose to pursue multiple versions of APIs in order to introduce large, or breaking, changes without negatively impacting existing clients of the API. One might argue that the use of clear APIs is a service-based, or Microservices approach, not strictly related to DevOps. However, the frequent cycles enabled by well-established DevOps processes are the tool to make APIs work together fluently.
Many organizations pursuing an API-first model find that doing so using containers helps them better manage technical debt by ensuring that each component of a service API is encapsulated and portable. This portability helps teams achieve a high degree of confidence that work performed in non-production environments, such as load testing or user acceptance testing in a pre-production space, will be representative of results observed when the code is live because a single artifact can be reliably deployed across all environments. Container orchestration platforms – such as Kubernetes – also help to reduce technical debt by handling many facets of scaling requirements natively – such as the Kubernetes Horizontal Pod Autoscaler (HPA). The time savings realized by combining increased confidence in code and testing with the time savings of automated scaling support can be significant factors in reducing direct technical debt as well as returning the savings to teams who can direct their attention to reducing other technical debt – such as by refactoring code.
Another strategy that DevOps organizations can use to better manage technical debt is to implement shared, self-service pipelines for common tasks such as compiling code, building containers, performing tests, or deploying to an environment – loosely an internal Software as a Service (SaaS) offering. By having these activities shared across teams, the organization can pursue a common technical language for discussing activities and issues. The process of designing, implementing, and supporting such a framework also necessitates that teams thoroughly discuss and document the requirements of the many applications that will make use of the available capabilities. The additional long-tail savings in time for both development and support teams further contributes to the management and reduction of technical debt.
Some organizations not pursuing a DevOps culture are oriented around large-scale project work, and tasks falling outside of the project level, or leftover from a previous project, become challenging to prioritize. The agility of DevOps organizations in recognizing, prioritizing, and executing one-off work below the effort of a project also provides an effective vehicle for technical debt payment.
Technical Debt is not always bad. Same as financial debt, it’s a tool, it can be used for achieving faster development and shorter time to market. However, when organizations ignore the accumulated technical debt, the interest on the debt may become too high. DevOps culture and tools serve as a good vehicle to better manage and scope technical debt. Another important point is that lack of proper DevOps should be considered today by itself as technical debt, so if your organization does have proper DevOps processes and automation abilities, at least in this domain, you are refraining from building technical debt.