Ward Cunningham is credited with the first use of the team Complexity as Debt or Technical Debt (YouTube video) as a metaphor poor software implementation. For a software application or system technical debt refers to the internal code quality. We have accrued Technical Debt when the implementation does not match current requirements or when implementation shortcuts lead to complex and coupled code. Over time people have added more and more items to the general bucket of technical debt.
Term Technical Debt has become very popular. Technical Debt has become the universal metaphor for characterizing refactoring work. Work that is technical in nature and not linked to features and functions. As a useful metaphor 'Technical Debt' has stood the test of time and is now used as an argument for driving investments in internal quality changes.
Martin Fowler describes technical debt and provides a categorization model in his article Technical Debt Quadrants. The article focuses on debt sources. There are many views and perspectives on technical debt. Bob Martin on A Mess is not a Technical Debt. Out in the wild Technical Debt is used for almost anything not related to feature function delivery.
In my own work, I have considered how categorization of and code volatility analysis can be used to guide when and how to address technical debt Metrics Based Refactoring
When Ward came up with the Technical Debt analogy software development and online systems were very different to today. The ecosystem that ran the software was much more static. Servers were bought and manually maintained. A lot of software running on desktops would be released once or twice a year. Patches and small updates were infrequent.
Today the number of software updates each day, week or month is mind-boggling compared to a decade or two ago. When there are hundreds of releases a day planned technical debt does not work. Planning technical debt work is not an option in today’s software development world.
A few years ago I heard the term Technical Health as an alternative term to Technical Debt. At first, I thought it was only a more positive view of the same concept.
Recently I have come to think that the technical health metaphor has a better fit than technical debt.
First, let’s look at some of the challenges with using Technical Debt as a metaphor:
The word debt is powerfully linked to financial management. Most consumers manage credit card debt. This direct connection between technical and personal financial debt. This direct connection is what makes the metaphor so powerful. As Ward points out building up a little debt can be a very useful thing in meeting objectives.
A challenge I see with this financial connection is paying off the debt. Technical debt is different. It often takes a long time to address even a small amount of debt built up in the code base.
We think of taking on debt as a deliberate act. Borrowing money today to take advantage of a situation or meet an obligation. Martin Fowler’s quadrant model only deliberate and prudent borrowing, meets this classification. Most technical debt does not come from deliberate and prudent borrowing. Today’s software exists in a toxic ever-changing environment. Software systems are more of a liability than an asset because it requires frequent updates and maintenance to survive. Tightly-coupled complex software is harder to change and update.
Maintaining working software in production environments is no longer an occasional activity. We have to think about maintenance all the time. Putting it off until later gets out of control to fast. 'Technical Health' implies continuous activity, making it more relevant to today’s software development.
Getting fit and healthy takes both effort and time. If you have an unhealthy codebase it is going to take a while to tackle the challenges. If the code base is unhealthy it is unlikely that you can clear up all the problems. Adding unit tests to an existing code base improves maintainability for example. Adding unit tests to an existing codebase provides a regression test suite. Changing legacy code is hard. It is much harder to change the legacy code so it compares with code developed through Test Driven Development. Sure you have better test coverage but this is more from a regression perspective.
Many organizations managing technical debt feel that an occasional investment fixes things. The expectation then is that it’s ok to run up debt between these investments. One-off or occasional investments encourages this behavior. 'If you have the cash you can solve debt at any time'. It’s a one-time thing and once paid up the code base is debt free, for now. Unlike financial debt, it is very difficult to recognize a zero balance. The investment runs out before all the problems solved. This background debt keeps building up.
Maintaining health is a cultural, habit-driven change. You can skip exercise for a while but it is then harder to get back into and will be harder when you return. Diet and exercise are an ongoing investment in time energy and discipline. The same is true for a healthy codebase. Time takes its toll. The software is more of a liability.
Libraries and operating systems need upgrading to handle security issues. Sitting on the shelf software deployability degrades.
Becoming healthy (fit) and maintaining it is hard (or at least it is for me).
Humans choose immediate gains over greater future gains. Making investments today that only provide benefit later is much much harder. That benefit may not be for ourselves it may be for some future team or others.
Refactoring is often done at the end of a development cycle. Cleaning up the code that now meets functional requirements. The benefits are found in the future. It is easy to say done when the code works - even if it is not clean or healthy.
We know that the security issues are a possible future problem but getting the next release often pushes such concerns down the road. Until they become a real problem and then we have the equivalent of a heart attack in software and have to drop everything to solve the problem.
If only we had spent just a little bit of time getting better at being healthy we would not have to contend with these crises.
The key difference between these two metaphors (IMO) is that Technical Debt focuses on explanation, Technical Health focuses on the ongoing change of habits. The debt metaphor is often interpreted as a single one-time transaction to pay down the debt. In the worst case, this might be the rewrite. Technical Health drives behavioral changes. Changes in day-to-day activities for code improvement.
Thinking about technical health promotes the changes necessary for changing habits. Making those changes leads to cumulative benefits over time. Making maintaining a healthy codebase a daily habit puts health generating work into a day of feature development work. They are not separated.
Ward Cunningham rightly points out that taking on technical debt to meet an urgent objective is often the right thing to do. Martin Fowler might place this in the Deliberate and Prudent quadrant. It is planned and understood to meet a goal. Teams taking on this kind of debt know that they will address the source code problems they introduce to meet the goal. This fits in well with the health metaphor. This might be considered as taking a break from the gym to finish up some urgent work. As a one of it does not affect long-term code health. It becomes a problem when skipping the gym becomes the norm because urgent delivery is every day.
Talking about technical health is positive. Talking about technical debt is all about a negative past. Developing a healthy code base is also positive but eliminating technical debt negative.
People are generally motivated to make things better. Cleaning up debt feels like a chore.
Focusing on the positive drives toward a better future. It’s about providing code goodness to your future self or to future colleagues.
Talking about technical health, what it means and how to achieve it is a better organizational goal than managing debt.