Advice on When to Repay Technical Debt
Henrik writes that it is “old debt” which we should be avoiding and aiming to pay off. He writes that part of getting a feature right and understanding a solution can involve a period of experimental trials and questions before arriving at a “simple elegant solution.” This debt should be paid off immediately. It is old debt which decays the software stack and leads to cumulatively slower delivery. He compares this with some every-day analogies:
If you open your computer to start on something new, and find that you still have dozens of windows and documents open from the thing you were working on yesterday, that will slow you down. Just like if you go to the kitchen to make dinner and find that the kitchen is clogged up with old dishes and leftovers from yesterday.
Hayim Makabee, Yahoo! research engineer and co-founder of the Israeli International Association of Software Architects, recently blogged an article titled “Avoiding Technical Debt: How to Accumulate Technical Savings.” He argues the case for technical savings, where good, yet adaptable design can result in paying debt upfront. He writes about the “Refactoring Distractor,” where too much time is spent refactoring later. Hayim advocates the paradigm of Adaptable Design Upfront (ADUF) through which he suggests that SOLID principles can be used to create component based designs around initially understood high level concepts. This allows changes in understanding to be addressed in concrete implementations and the interactions between components. ADUF has some resemblance to XP founder Martin Fowler’s stance on Evolutionary design replacing Big Up Front Design. He previously wrote that “designers need to learn how to do a simple design, how to use refactoring to keep a design clean, and how to use patterns in an evolutionary style."
Writing about ADUF, Hayim explains a practical implementation of this style:
Each component in a framework should be designed to be highly cohesive, and the framework itself should be designed so that components are weakly coupled. If the component interfaces are indeed abstract and if the coupling among these components is weak, each type of component in the framework can be seen as a kind of plug-in.
Inventor of the term “Technical Debt,” Ward Cunningham was interviewed by OnTechnicalDebt.com earlier this year. In discussing the payment of technical debt upfront, Ward suggests that it is an option if you don’t want to “take the risk of spending money you don’t have or shipping code with half the function points.” He also points out that in the modern continuous delivery world, there are acceptable levels of bugs and bad design:
...there are, of course, a lot of approaches to software that work, one that kind of surprises even me now is this notion that people who run big websites and are capturing logins as fast as they can are inclined to say that they’re less concerned with quality than they thought they needed to be and more concerned with resilience – that is the ability to push forward even in the presence of a mistake.
Henrik explains that software is never perfect and that the opportunity cost of writing debt-free code would be seen in delivery times.
In theory, it would be great to get down to zero technical debt after each feature. In practice, there’s an 80/20 rule involved. It takes a reasonable amount of effort to keep the technical debt at a low level, but it takes an unreasonably high amount of effort to remove every last last crumb of technical debt.
He proposes introducing a debt-ceiling for dealing with aspects of debt which seep through the process crack. Although most new-debt would be paid off in real-time, when the debt ceiling is reached, all resources should focus on reducing the debt level:
The debt ceiling should be set high enough that we don’t hit it all the time, and low enough that we aren’t irrecoverably screwed by the time we hit.
Hayim’s ADUF pattern presents an approach which can be used to make such up-front savings, although we may never arrive in a state of zero-debt. Henrik and Ward have reminded us that acceptance of technical debt is a compromise which we willfully make in order to deliver a viable product in an acceptable time-frame. Hendrik ends his piece by pointing out that more debt we accumulate the more we stagnate future development and team moral. Through monitoring technical debt, Henrik has shown us that we can better understand our risks and platform health. Managing our level of technical debt and planning to pay this back, is something which we must then actively prioritise.
A clean code base is not only faster to work with, it is more fun (or less annoying, if you prefer seeing things that way…). And motivated developers tend to create better products faster, which in turn makes both customers and developers happier. A nice positive cycle.