Messy Code is not Technical Debt

Technical Debt is a common topic these days. How is it incurred? How should we track it? When should we pay it down?

It is a metaphor commonly understood. Our customers get it. While they may not like it, they do understand. Technical Debt is incurred today and needs to be paid down; preferably sooner rather than later what with compound interest and all that.

Technical Debt is accepted by many as a natural part of the development process. Frankly, I agree. I think Technical Debt is a good thing to take on for short periods of time. Perhaps it is even unavoidable in some cases. Therefor we should expect it and deal with it accordingly.

But there is something insidious going on here. In many cases, perhaps even most cases, what developers are really talking about is code that is not Clean.

And Messy Code is not Technical Debt.

What is Technical Debt?

Ward Cunningham coined the phrase Technical Debt.
"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. Objects make the cost of this transaction tolerable. 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."
As he clarifies later in a You-Tube video, Ward was specifically talking about design decisions made in the course of developing software that allowed for more rapid delivery. Rapid delivery not for the sake of meeting a deadline. Rapid delivery to elicit quick feedback, thereby providing the data necessary to adjust the design to be more congruent with actual needs. The object design should change to reflect your current understanding of the domain, even if that understanding is partial. Technical debt is payed back through code refactoring as our understanding of the domain matures.

Ward clearly states, "The ability to pay back debt [...] depends upon you writing code that is clean enough to be able to refactor as you come to understand your problem."

Misunderstandings about Technical Debt

Ward's original description was vague. His clarification which later followed may have come too late. Many had already taken the phrase and added their own flavor to it.  Martin Fowler discusses Technical Debt and even refers to Ward's definitions, but then goes on to say "doing things the quick and dirty way sets us up with technical debt". Jeff Atwood also allows the phrase "quick and dirty" to creep into his explanation of Technical Debt. And in an Intel posting, the definition is expanded to:
"Technical Debt is loosely defined as the volume of poorly written lines of code, poorly refactored, not following coding standards, not supported with sufficient unit tests, and the amount of code duplication."
This seems to be the common definition of Technical Debt today. And it is most unfortunate.

Messes are not Technical Debt

Poorly written code, lack of standards, lack of tests, code duplication, multiple responsibility, complex interfaces, large classes, poor/insufficient error handling, and opaque intent are all messes. Not a one of them is Technical Debt. And as such, none of them should be categorized as Technical Debt. For a comprehensive listing of messes, see Robert Martin's Clean Code.

Messes Preclude Technical Debt

Technical Debt is paid back through refactoring as our understanding of the domain matures. "The ability to pay back debt [...] depends upon you writing code that is clean enough to be able to refactor as you come to understand your problem."

Clean Code is actually a prerequisite for Technical Debt. If you don't have Clean Code, you cannot expect to pay the debt back. If you have a mess, you cannot reasonably incur Technical Debt. In fact, you are not incurring debt, you are merely adding to the existing mess.

Messes are not Acceptable

Uncle Bob has stated, "There aren't any reasons to make a mess."

I don't entirely agree with Bob on his point. I think there aren't any reasons to leave a mess. TDD encourages us to take tiny steps. Some of these steps result in small messes. Messes that we will clean up in very short order. But we've made a mess nonetheless. And there is no shame in having done so. To leave the mess for any significant period of time or to allow more mess to accumulate is, however, unacceptable.

Stop calling messy code "Technical Debt"

Stop hiding behind the term Technical Debt. If you have messy code, clean it up. Implement the Boy Scout Rule and get it taken care of.

Most important - don't treat the permeation of mess into your system as something natural and acceptable.


  1. Doc,

    A former manager of mine agrees with you. He said, "If you do it quick and dirty, then when quick is done all you have it dirty." We don't want to leave dirty code as our legacy for those who come behind.

    Also, Smokey the Bear tells us to leave it a little cleaner than when we arrived. I think that is good advice.

    Dennis Stevens

  2. The use of Technical Debt to mean "the debt load of an unconsolidated implementation, object-oriented or otherwise" was around before Ward Popularized it in his '92 paper. (I first heard it used that way in '88 in the context of deferring a compiler upgrade, in much the same way that Ron Jeffries used the phrase in '95 in to describe decisions to defer GemStone upgrades.)

    If you have a code mess, and the mess is impeding development, what do you gain by arguing that you don't have Technical Debt? Avoidance of stigma?

  3. Dave Smith

    Thanks for the feedback. I could not find any attribution to the phrase Technical Debt prior to Ward's use. Attribution to Ward is extremely common -

    That aside, I fear you've missed my point. This is more significant than semantics or stigma.

    Technical Debt is an acceptable occurrence in the development cycle. To overload the definition of Technical Debt with items that are actually Messy Code is dangerous. This implies that messy code is a normal and acceptable occurrence in the development cycle. It is not.

  4. The question is where to draw the line. I accept that mess is technical debt, albeit a particularly dangerous form of debt. I think this is what Ward is saying at 4:28 into the video.

  5. "This seems to be the common definition of Technical Debt today. And it is most unfortunate."

    If that's the common definition, then it's the definition. Unless we're trying to own the term for a more specific (scientific?) purpose. Otherwise, this is just the old "hacker / cracker" debate.

    I think that we're seeing a lot of conceptual confusion because a lot of people in the real world still deal with a lot of messy code. A concept of technical debt that doesn't include "code you wrote when the desire to meet deadline overrode the desire to be correct" isn't as useful in a real-world discussion.

    Sometimes an incorrect (from initial usage) generalization of a term isn't a bad generalization.

  6. Well said Mark! I'd like to add, the solution for messy code and technical debt is generally the same: Time to Refactor.

  7. Well said Mark! I'd like to add, the solution for messy code and technical debt is generally the same: Time to Refactor.

  8. Of course there's a reason to make messy code: It saves time. That's the entire point of technical debt. It saves time in the present but causes time to be lost in the future. Sometimes, that tradeoff is worth it, other times, it's not.

  9. Here is a transcript of the video -

  10. My comment started getting a little long, so I made it a blog post.

  11. Maybe a useful way to look at it is that Ward is describing responsible debt. Messy, quick and dirty coding is like refinancing your house to take a vacation.

  12. Of course messy code is technical debt... the association is transparent.

    If you write messy code, then release it, you must then go back and fix that messy code, in the simplest form that IS a debt you must repay, therefore is technical debt.

  13. The other reason that messy code happens is because people are learning.

    Unless you start with a team of developers born to produce beautiful, clean code, the chances are that someone on that team will be learning. In that respect, messy code _is_ a normal part of the development cycle, as is having it left around.

    (Even a team of star devs learnt somewhere!)

    So, it's not just about taking the time to refactor - it's about helping people learn. Stigmatising either technical debt or messy code isn't helpful, IMHO - it happens, it will always happen, and having tools and the will to continuously improve is probably more useful than trying to avoid it in the first place.

  14. It seems to me that the question lurking in the background involves what is left of the concept of technical debt if you exclude "messy" code from it - and what does this concept do for us? If you're not arguing that technical debt should be abolished as nothing more than a euphemism for sloppiness then I would guess that there's a form of "non-ideal" code that is different from "messy" code and is acceptable in certain circumstances. Is this well-written but incomplete code, with omissions clearly indicated by ToDo tags or something similar? Refactorable code versus code requiring a complete rewrite? What do these differences look like? Those are the questions, I think, that this discussion might focus on.

  15. Messy code is just a loan from a loan shark, taken under duress to pay your previous gambling debts.

  16. Ward's Latest input on the topic -

    Dirty code is to technical debt as the pawn broker is to financial debt. Don't think you are ever going to get your code back.

  17. I think poorly written code and duplicate code can be referred to as messy code. And according to the definition, technical debt refers to poorly written code and duplicate code. So I am not convinced with the fact that messy code is not Technical Debt. Also, errors or bugs which get accumulated over time lead to technical debt. These errors or bugs can be said to be caused due to messy code.

  18. I've been in the same boat as the speaker in the video and have had to explain this to bosses on many an occasion.

    What specifically can constitute a debt in coding varies but assuming it is wittingly it is always a consequence of choosing the present over the future. Generally speaking, it's anything that incurs a cost in the future. If you have a thousand tasks then what you do in the first one hundred will impact the resources requires for the next nine hundred.

    Messy code can constitute a technical debt. A mess can be a lot of things by definition but more important is its impact in maintaining code or systems which tends to be universal. Messy code harms maintainability as it is hard to debug and often, almost by definition, lacks consistency and patterns that make it easy to modify or add to.

    The blame for messy code can come down to the individual who may lack discipline or management that has decided to go cheap.

    Where messy code can be different is that the cost of writing clean code is often little different to the cost of writing messy code for an individual in the first place. Where this is not the case, the individual lacks certain skills for efficiently making code tidy. There's little to no real short term benefit but rather a long term cost. The true debt here is hiring the wrong people or failing to enforce discipline.

    Like anything else, messy code means that after cycle A cycle B takes more effort. Any work on messy code will be harder than on clean code so as long as messy code exists and is being worked on your are forced to pay off this dept or the interest on it whether you want to or not. To pay off the dept in full you must clean all of the code. This is costly as cleaning code can introduce new bugs and messy code is very rarely aesthetically messy but disorganised across the file system, structured poorly and bloated. People who code in a messy fashion as also exhibiting a mental flaw which is not compatible with programming and that is absence of a general desire for order so the mess will likely penetrate even into the program logic and flow. This means you'll need more than a beautifier. The long term costs of messy code can be drastic. Even a small amount of mess in the right place can act as a landmine because mess can beget mess. The mess will also lead to more bugs.

    Messy code is only one possible part of debt and a low level one. Generally debt builds up when you have bad project management where, for example, all the work is spent on implementing features back to back with no slack time to do all the little things to keep everything running smoothly. Code cleaning is one of those things if your code is a mess. Alternatively it can be refactoring or simple improving the software in general. Mess can accrue from this rather than individual errors typically due to too many bolt-ons and no time to deal properly with legacy artifacts that turn out to have been incompatible with the future.

    1. The "speaker in the video" is Ward Cunningham, the man who actually coined the phrase Technical Debt. Per his definition (and the definition I think we as a profession should adhere to), messy code is not technical debt.

      Thank you for your well written response.

  19. I'm agreeing with George D. here, and perhaps a few others: I appreciate your not wanting to call sloppy coding debt, but as there are appropriate debts and safe mechanisms for taking on debt in the financial world, and dangerous, inappropriate forms as well, so too with technical debt.

    The reason why I would still call it debt is to acknowledge that something really does have to be done about it, else it will have a direct impact on the bottom line. Messy code is really poor "Design Debt" and "Testing Debt" (according to my personal taxonomy of debts, described here: Please note: I've refined my views on tech debt since then, but the taxonomy still works for me): Sloppy code written without tests. And there are things that can be done to pay down sloppy debt: Careful, surgical refactorings, followed by characterization tests.

    So my thanks to you for challenging the notion that people can be careless now and pay it back later. They won't. Or when they do, they need a lot of (my) expensive help. 90% of the code I see out in the wild is indeed sloppy, untested crap (and proving Sturgeon's Law is not an aspiration but a curse).

    But we won't get folks to change behavior by saying "stop that" or trying to more narrowly define a term to exclude 90% of what people actually build: We have to suggest better ways to work.

    E.g., TDD includes and relies upon relentless refactoring. TDD Saves! ;-)