Thursday, July 23, 2009

Good Technical Debt vs Bad Technical Debt

Early today I was reading a short blog post over at Scrumology on an age old argument about the fine balance of technical debt and releasing early.

Accumulate too much technical debt and your product's development will slow to a crawl attempting to service all the debt you have burdened yourself with. If you spend too much time keeping yourself debt free, you will miss your opportunity as your product's all important time to market is too slow.

So where do you draw the line?

I think we can draw a lot of parallels with financial world. As the article and its links point out, there is good debt and bad debt. Good debt is debt that builds value (business loan) or the opportunity to build value (student loan) and/or builds happiness (mortgage). Bad debt is debt accumulated to gain things that rapidly decrease in value; they worth less than the debt took on. Think clothes, or that new big screen HDTV.

For technical debt to be good debt you need to gain more then it will cost to retire it.

If you can close a big deal by adding a feature to your product within a really short time line, then it makes sense to do so. You after all have bills to pay, you can get feedback from your customers, and your team will get to celebrate a success and build momentum off of a big win. This can really help morale. (Of course adding features to win deals from specific customers is its own bag of worms, but let's just assume for the sake of argument that this feature is an awesome feature that you were planning on releasing in your next major release, but the customer couldn't wait that long.)

Another example of where technical debt is good debt is in cases where the product/solution is a one off, spending too much time and effort on a clean design is simply wasted effort and not needed. The code will rarely be modified. In these cases you only add to the cost of the product.

And in those cases where the products are not one offs, there is a concept of "luxury design" in my opinion. Especially when considering architectures that need to "scale" or other such "not needed yet" nonsense.

If you are creating a new product to release you don't need to worry too much about "scaling" upfront. Having scaling issues is a "good thing". It means you are successful. It means you have the resources and the business case to go ahead and put the right architecture in place so you can scale to the next level. But putting that in too early and you could miss your market window. You have missed your chance to build value and wealth, and to gain customers.

There are of course cases where you cannot accumulate that debt because the cost is simply too high. For example, adding a new feature to a successful ecommerce website where if the customer experience drops due to performance or bugs you get big a drop in revenues. Here you have the data to prove it that the debt is bad. There is a direct and immediate cost.

Of course with gobs of money and time, you can have the best of both worlds. With a proper user-centered design approach to product creation, your user experience team will be doing user research, and running user tests with mockups and wireframes while your team off building components and backend pieces. It's too bad that this is not more commonplace, users around the world would rejoice.

There is an old adage that nothing in life is certain but death and taxes, and in product development I will advance a new adage for consideration. "Nothing in product development is certain but technical debt and too early release cycles".

What do you think? Should technical debt be kept to an absolute minimum, or is a more pragmatic approach needed?


Pawel Brodzinski said...

First, technical debt is never a good thing. It's always bad. Sometimes you can accept it not because it's good but because other choice is worse. But it's still bad.

Second, I believe we generally accept technical debt too fast and too easily. Very often effort needed to design application properly isn't much greater than effort needed to design application fast. The problem is we rarely consider it consciously.

Third, the example of scaling up is, for me, a typical case where we make wrong decisions on technical debt all the time. To give one example from my experience - writing message processing in multi-threaded architecture wouldn't bring much more work than doing it single-threaded. Unfortunately we didn't consider "scaling up" issue. We ended up hitting the ceiling very soon and rewriting huge part of the very core of our solution, which wasn't only time consuming but also invited loads of new bugs. We ended up being significantly late with the project, which could be easily avoided if we did the right thing from the very beginning.

Adding features is a bit different story, but accepting technical debt on architecture and design phases is usually wrong decision. You gain to little and you risk too much.

Jason Mawdsley said...

Hey Pawel,

Debt is debt is debt. I don't like any debt including my mortgage. But I accept my mortgage because it provides us with a standard of living that my family requires.

Technical debt can be considered along the same lines.

The point I am trying to make is that technical debt isn't neccessarily bad, and can provide more benefits then not. Whether you consider it to be good debt or not is merely semantics. If you are realizing more value from the hack you put in then you would without it, that is good. Even if the hack isn't.

The other point I was trying to make is that we all too often spend too much time and energy designing the most optimal solutions possible, and they are not always even required.

There are differences in a crappy dead-end design, a good enough design, and the gold standard design.

The good enough design should have some minimum requirements, but doesn't necessarily need to think of _absolutely_ everything