Ward Cunningham, a fish of some note in our small pond, wanted to deliver software incrementally to a client in the financial sector. The client didn’t see the value in doing that as opposed to delivering in a “big bang” fashion. To help relate the idea to the client’s frame of reference, Ward came up with the “technical debt” metaphor. It’s explained pretty well in an Agile Alliance article.
I say the article explains the idea “pretty well,” and not “well,” because it doesn’t really zoom in on a key point. Ward clarifies it himself in a video you can find on the c2 wiki. Part of his explanation reads:
“I’m never in favor of writing code poorly, but I am in favor of writing code to reflect your current understanding of a problem even if that understanding is partial.
“You know, if you want to be able to go into debt that way by developing software that you don’t completely understand, you are wise to make that software reflect your understanding as best as you can, so that when it does come time to refactor, it’s clear what you were thinking when you wrote it, making it easier to refactor it into what your current thinking is now.
“In other words, the whole debt metaphor, let’s say, the ability to pay back debt, and make the debt metaphor work for your advantage depends upon your writing code that is clean enough to be able to refactor as you come to understand your problem.”
So, Ward never meant to advise people to write sloppy code in a rush with the idea they could come back later and clean it up. That never was the meaning of “technical debt.”
The meaning is more along the lines of this (my paraphrase):
“We think we know some of what we need to write based on our current understanding of the problem, so let’s deliver that to get feedback from users to improve our understanding. For this approach to work, we must keep the code clean at all times, so it will be feasible to refactor it or modify its functionality without getting into a nightmare scenario.”
The “debt” is the missing parts of our understanding of the problem and the necessary solution; not the quality of the code we write. Whatever code we write, we’re expected to write as well as we can. Always.
That’s very, very different from the way most people seem to interpret the phrase, “technical debt.” Some people understand technical debt to mean sloppy code. Others understand it to mean components of the technical infrastructure that have grown outdated and are overdue for an upgrade or replacement. Neither of these corresponds with the original intent.
Using not-exactly-technical-debt on purpose
That said, there are times when people deliver a software solution that isn’t “fully baked” or as “refined” as it might be, quite deliberately, to achieve an early release. It’s not done as frequently as it’s talked about, but it does happen. Most people haven’t done this or even seen it, so there are comments like this on social media:
Here’s a story. I was working for a large-ish bank around 2003 or so, and a business unit manager wanted to take advantage of a market opportunity. It seems there was a trend among nouveaux-riches poseurs to purchase luxury boats. When a member of the club obtained a larger boat, then everyone else was keen to upgrade to an even-larger model.
Several banks were interested in tapping this then-emergent market. In our case, the existing loan approval process took two days, even when amped up to full adrenaline levels. In two days’ time, a would-be buyer could go home, sober up, and get some sleep. The whole boat thing didn’t look as shiny in the stark light of day. So the business opportunity was to turn around loan applications in five minutes, on the spot, while the customer was still in the showroom with pen in hand and pupils dilated. First-mover advantage was estimated to be around 76% market share.
The business unit manager came to our skunkworks XP team and told us the official IT department had estimated a 10 month project involving 24 people, at a cost of some $850,000. She wanted the solution in place by May of the current year. This was in February.
The solution would have to involve handheld wireless client devices at a time when that sort of thing wasn’t as common as it is today. The bank’s IT department had no infrastructure in place or people with such experience. They said they didn’t know how to do it. We replied that many people out in the world knew how to do it, so it was do-able. Unfortunately, they had a bad case of Not Invented Here.
Furthermore, to complete the process the new application would have to access borrower information from an EDS-hosted CICS application for which there was no API. EDS said they would write an API for us. It would cost $144,000 and take four months.
The business manager figured if they could get this in place by May, they stood to make some money in the current year as well as dominating the market (within the bank’s footprint) to the tune of some $2 million per year. Not huge money, but good money. On the IT department’s schedule, assuming both they and EDS could deliver on the estimated time frame, they would have nothing in place until Year Two, and would be the third entry in the market. That would give them very little market share.
Long story short, we assembled a team of four and completed the whole thing in 6 weeks at a cost of around $73,000. We did the XP thing and the key business stakeholder participated in the role I would later learn was called “Product Owner” with no training. She could do that because to a profit-minded business person, there’s nothing mysterious or odd about “agile” thinking. It’s only mid-level IT managers who struggle with it. Business people make high-stakes decisions based on limited information on short notice all day long. Business people know all their plans are point-in-time best guesses, and everything can change at any time. It’s nothing “new” to them. They don’t call it “agile.” They just call it a weekday.
What about “technical debt” that wasn’t really technical debt but was just a quick solution? Right. Well, to pull the data off the EDS system we did a screen scrape. All the technical people in the bank who heard about it were horrified. That was just not a “clean” solution. It was going to cost a ton to support. Yadda, yadda, and yadda again. And later: More yadda. It was yadda out the wazoo.
The bank made $700,000 the first year, and averaged around $2 million per year thereafter. After the first couple of years, I visited the business unit manager and asked her about that solution. She said it was still running, and it had earned enough to pay for its own upgrade. They were replacing the screen scrape with a proper API. The market concept was proven.
So much for “no one ever goes back and cleans up the code.”
I visited the manager of production support and asked what the costs of supporting the screen scrape solution had really been. Looking it up, he found that the screen layout had changed three times over the past two years. Of course, EDS didn’t notify us, because they didn’t know about the screen scrape. So the three changes resulted in production support tickets. Calculating the amount of time that was spent in fixing the solution and the cost of the personnel who did the work, the average annual cost of support for the screen scrape solution was $135.
So much for “a solution that isn’t perfectly engineered will be too costly to support.”
What if the market concept had turned out to be a loser? We would have invested $73,000 and 24 person-weeks of effort to find out. Had the IT department won the day, we would have invested $984,000 and 960 person-weeks of effort to find out. Win or lose, the “technical debt” approach was the right choice.
Was that really “technical debt?”
Yes. No. Maybe. It’s a borderline case, I think. The screen scrape can be considered suboptimal technical design. In that sense, the story exemplifies the situation when a technical team takes a “short cut” that isn’t a completely sound design. But the solution was also an example of the situation when a team delivers as much as they know about, built fairly solidly, and then learns from customer feedback what to do next. From that angle, it looks a lot like Ward’s definition of technical debt.
Does the screen scrape rise (or fall) to the level of “sloppy code?” Our technical colleagues in the IT department thought so, loudly. But in hindsight, I wonder if it isn’t an example of something quite different. Earlier in the “agile” movement, before it all settled down into a global sales pitch for scaling frameworks, people in the community used to think about innovative solutions and new horizons for agility. No, really, I’m not kidding. They did. You’d never guess it today, but that was part of the idea all along. I’m pretty sure it was, anyway.
Some of that thinking pertained to how a team can deliver a fixed scope on a fixed schedule, or at least as much of the planned business value as possible. One line of thinking was that we don’t actually reduce scope as such, in the sense of removing features entirely, but we simplify the solution. Say you had a UI design that called for a drop-down list of options. Ideally, you might want to pre-populate the list from some back-end data store. But to meet a challenging delivery date, you could deliver the solution with a simpler UI widget that wasn’t pre-populated. It places a bit more burden on the user to know and enter valid values, but it still “works.” The solution offers the same business functionality, but the implementation is simpler so it can be delivered “on time.”
Different people thought of this approach independently of one another. Two I know of were the Belgian consultant Koen van Exem and the UK-based consultant Karl Scotland. Koen called the approach “dimensional planning,” and Karl called it adjusting the “fidelity” of the implementation. I’m not sure either name captures the intent especially well, but I hope the idea is clear enough. You’re not reducing scope because you’re not removing any features. You’re just building the features in a cruder way, initially. Not in a sloppy way; just a less fancy way. The idea is you’d come back to that feature in a subsequent release and polish…if it proved to be worth doing so.
What we did with the screen scrape in the loan approval solution was exactly that. All the necessary business functionality was supported; no features were omitted to “reduce scope” in order to deliver by May. But the initial solution was crude. Once it had proven itself in the market and was generating revenue, another team went back in and replaced the screen scrape with a proper API. It worked out quite well, I’d say.
Conclusion (or just more questions?)
Neil’s observation struck me as interesting because it contains (or implies) more than one question. What’s “technical debt” supposed to mean? What does it mean on a de facto basis to the majority of developers? Does it matter? Does anyone incur technical debt deliberately in order to accelerate delivery? If so, how do they do it? Do they compromise the quality of the code, or remove features, or build all the features using sound software design practices but with a simplified implementation? Something different than any of those?
For what it’s worth I agree with Ward that compromising the quality of the code is not the way to go in any case. But there are ways to try and get ahead of a tight delivery schedule or to put something into customers’ hands quickly so you can get their feedback. We don’t have to be sloppy to achieve those things.
Whenever a developer tells me they “had to” be sloppy in order to “go fast,” and that the sloppiness is someone else’s fault for putting “pressure” on them, it gives me pause. Sloppiness is a choice. Besides, it doesn’t help us deliver “faster.” That’s always been a myth. There’s no need to be sloppy. Other practical choices are available, and they yield better outcomes.