Code Debt is the debt we incur when we write sloppy code. We might do this to rush something out the door, with the plan to refactor later. Agile methodologies focus on delivering functionality quickly. They also invoke a mantra of refactoring – “make it better next release.” This can create pressure to “get it done” that overwhelms the objective of “get it done right.” Taking on code debt like this is about as smart as using one credit card to pay off another one.
Using Timeboxes to Visualize Pressure
In our timeboxing tutorial, we introduced a framework for managing releases and the amount of work we do within each release. We can apply the same framework to visualize the pressure that makes us consider borrowing against our future to take on a code debt.
Here’s a quick summary of the concepts from that article.
Each unit of functionality that we deliver in a product or release is made up of two elements – the time it takes to make it, and the time it takes to make it right. We can think of this as function and quality respectively. We;ve drawn them as puzzle pieces to show that they are (or at least should be) locked together. When a developer gives an estimate, it should be for the combination of function and quality – not quality alone.
A timebox represents the amount of time and money we allocate for a given release. It basically determines the size of the box that we can fill up with our units.
In our article, we talked about the options we have to try and get more “stuff” delivered in a single timebox. One obviously bad option is to decouple the quality from the functionality in order to deliver more functionality.
Several people essentially said “No one would ever plan on bad quality – that’s a bad suggestion!”
We agree – it is a bad idea. We were merely pointing out that it is something people consider. Especially managers who’ve never read The Tipping Point, and don’t know about “broken windows.” “Broken windows” in this case is a reference to the downward pressure that is applied to all future development efforts by forcing developers to work on a code base that has a lot of “low quality code.” The idea is that if we skip the quality part enough times, we will eventually stop caring at all.
We also agree that rational people won’t make a habit out of using this approach. However, there is another way we could find ourselves in this situation.
What if our estimates were wrong? In the middle of the timebox, we suddenly find ourselves without enough time / people to finish.
In the highlighted region of the diagram, we can see that the feature on the left took longer than we expected – and it pushed out the red/orange feature. There isn’t enough room in our timebox to get it all done.
Guilty
We’ve even suggested that maybe the right thing to do is to take a loan against ourselves and incur a code debt.
There are times when incurring a temporary code-debt is pragmatically more useful than delaying a release or a feature in order to polish the code.
I’ve also argued against code-debt as a long term strategy, in the comments on another post.
I definitely agree that code-debt builds over time and gets more and more expensive. Plus there’s the risk of the whole ‘broken windows’ problem that Malcolm Gladwell outlines in The Tipping Point. I visualize it like the graph for a cascading diode – you can build up more and more code-debt (or design-debt, as you describe in the link), with its associated performance penalty, until you reach the ‘critical voltage’ and flood the diode. At this point, it becomes impractical to refactor – rewriting becomes more cost effective.
So, we’ve stated that it might be a pragmatically good idea in the short run, and definitely a bad idea in the long run. But how do we crystalize the message that it is risky? With another good analogy.
Another Good Analogy
We owe our thanks to Mishkin for this extension of the “code debt” analogy that brings perfect clarity to the issue.
Last night I was thinking more about the analogy of technical debt. In this analogy, design and quality flaws in a team’s work become a “debt” that must eventually be paid back.
[…]
In other words, every time someone asks a team to let quality slide, they are asking the team (and the organization) to take on debt with an unknown interest rate. Which is lunacy.
Thanks Mishkin!
Conclusion
Technical debt is very risky. Maybe it is the right call in the short run (but assume it isn’t). It is never the right call in the long run.
Good article. We’ve just recently adopted the notion of “technical debt” within one of our development teams. The developers own a backlog of technical debts, just as product management owns a backlog of new features for the market, and the customer support team owns a list of bug fixes and enhancements.
Its important that someone owns the list of debts, though. Otherwise, they are quickly forgotten.
I wonder what an interest rate scheme would look like on tech debt? Anything that helps put these things in terms management can understand ends up being helpful :)
Hey Patrick, thanks for reading and commenting!
You mentioned three different lists (refactoring / new functionality / bug fixing) with different owners. How are you managing those? Are you dedicating x% of dev resources to each one in a given release (where prioritization is separate for each list)? Or are you prioritizing the aggregate list of all items?
I think either approach is workable. A single prioritized list would help the team stay focused on the most important stuff. Three lists, with dedicated capacity to each would help a team maintain a particular strategy or vision.
Please tell us which approach your team is using.
As to interest rates – I think Mishkin is right – we don’t have a reasonable way to know. “Bad code chunk X” will have an unknown long term impact. We have some short term visibility, but we don’t really know. Here’s an example:
User authentication is “hacked together” and the product is launched. It works great for new user signup and login. What is the interest rate?
If all scheduled dev work surrounds other functionality that doesn’t touch the authentication functionality, then the interest rate is low.
If the plan is to move to LDAP (external) user authentication, the interest rate would be high. Background – LDAP is a feature that would allow users to not have to log in (if they are already logged in to their network) to be authenticated. These changes would be likely to touch the previously “badly written” code.
Hi Scott,
Our approach is to sort and maintain those lists independently, then create a single aggregated list during a release planning session. As such, there is no dedicated percentage of development time to each list. Subsquent iteration planning meetings are held to review the merge decisions that were made up front during release planning, just to ensure any new information that comes up can be put to use.
This merging of the lists does add a little bit of time to the planning process, but it is time well spent. The aggregation process forces our different stakeholders to periodically meet to discuss the issues, determine what is most important for the product at the time, and to coordinate the execution of the plan. Since those stakeholders have to be present to perform these sorting tasks, visibility into the process gets a huge boost.
As for the interests rates, I think you’re right to consider how much the “hack” affects future development efforts. The LDAP example is a great one.
Thanks for the feedback!
Patrick