Embrace technical debt
startuplessonslearned.blogspot.com
startuplessonslearned.blogspot.com
There are real negative consequence of applying a "broken mental model" -- you end up doing the wrong thing when you live by the model!
Why is technical debt a broken concept? Real Debt is incurred proportionally to the asset bought with it. In technical debt the debt is proportional to the trouble it causes, not the value delivered. Also, it implies that the only way to get rid of the debt is to make a big investment. In reality, you can just throw away code and the debt disappears. Not analogous with real debt!
It should've been called technical drag. Properties of drag that are appropriate to the metaphor: - You get value based on the amount of input work, but it places a drag on the overall progress towards the goal (support load, architectural coupling). - You can reduce the drag of an existing component by investing to refine it. - New components typically add more drag than existing ones. - Little bits of drag here and there add up to a big problem - Removing unused functionality reduces associated drag without major investment
Thoughts?
Technical debt is closer to this than you might think. This would be "going bankrupt" on that code. It's like having a loan secured on the value of some object. If you want to default on the loan, you lose the object, nothing more. (Although you don't lose your good credit rating as you would with real debt!)
It is not going bankrupt on that code, When you go bankrupt, there is a huge penalty to your credit! If you stop maintaining code that no one uses, the drag goes away and there is no downside!
Deleting code is fun. Going bankrupt, not so much.
This is why I like the "technical debt" metaphor more than the "technical drag" metaphor. Technical debt acknowledges that there's an outside user who's presumably paying you for the project. You can choose to satisfy them better now, but it's at the cost of satisfying them less later, or even regressing and making things more painful for them as you take away debt-ridden features. Just as how financial debt lets you invest now and satisfy the immediate customer better at the price of paying it off later.
"Technical drag" implies that forward motion is inexorable, and the only variable is the rate. This is not a given in software; I often try to use old versions because I know that new ones will be slower, more cluttered, and buggier.
Did you read the article? Eric Ries gave a good example of a piece of code that they had built, with technical debt, and which they threw away because it had little or no customer value.
In practice, I see it happen all the time. There's functionality in most applications that could probably be removed with little impact to user experience. Even on Woobius there are some chunks of functionality that are not much used at the moment and that we could remove without much impact on the users.
We could just call it "technical venture capital". You make a large number of investments, the majority of which have absolutely no value to consumers. You abandon the losers, sometimes after much handwringing. It is usually impossible to tell a priori which features will be winners and which will be losers, though experience and good technical judgment can improve your odds. You can invest more in promising features to bring them to market quickly. Doing so usually introduces lots of warts into the codebase which will have to be fixed later - but then, you'll have lots of money later to fix them. But you have to be careful to avoid investing too much too early, before you've seen how the feature will actually play out, because then you build a giant monstrosity that collapses under its own weight before it can ever get to market.
Or we could accept that all metaphors are imperfect. I'm going to continue calling it "technical debt", because most people - even if they haven't heard of the term - have some idea what I'm talking about when I mention it.
It's easier to type that sentence though than it is to actually come to that conclusion. Assessing customer value, or even better, which customer between two competing customers matters more is the hard part.
You don't solve technical debt with technical decisions, as it's a symptom of business process scope creep.
Unnecessary code is not technical debt. Code supporting unnecessary process is technical debt.
http://inter-sections.net/2007/12/01/comparing-pieces-of-str...
"Technical drag" is a very good term for it, I agree.
For instance, I used to manage some poorly architected Java apps where even trivial changes incurred painful re-architecting because the app was poorly written. And I've managed PHP apps that are extremely well-organized and are very simple to add functionality to.
The other thing I'd mention is I like your idea about hitting the wall where improvement freezes b/c the implementation time is so great. I think it's a good fit for the technical drag model -- that is the point of terminal velocity!
It's another good-fit for the metaphor; eventually you can only drive forward a product by making the team bigger because your project hits its terminal velocity (or top speed) for the given "engine" size (the team).
A particular engine architecture scales proportionally up to a point, but then gets harder to get a little bit bigger. Same is true with dev teams...
Secondly, with debt comes the concept of interest, which is the most salient point. The big problem with technical debt is that you can have a small amount and there are essentially no downsides, but the longer you avoid paying for it, the harder it is to avoid creating new technical debt when you write new code, the more technical debt you will incur, and the negative effects start to compound.
On your second point, I do agree that there is a strong salient aspect of the idea of interest payments on debt. Like I said originally, the metaphor stuck because it resonates. However, the idea of technical drag has this same exact concept; the more junk you bolt on to the car, the more it overwhelms your project, and your initial F1 racer becomes a UPS truck.
One could make a point about technical debt that technical drag doesn't have, and I'll yield it's important, is that it's pretty tough to have so much drag you can't move. Whereas debt service can flat-out sink you.
However I'd counter that if you aren't moving (ie have customers using your software) then technical debt isn't really a problem because you don't have to do much work to service software with no users. Whereas technical debt implies that you have to pay for the feature even if it isn't being used.
With a poor design, it can be more difficult to make changes to improve scalability. If you do not have abstractions and information hiding that allow you to switch out algorithms, libraries or systems for ones that scale better, you will need to rewrite a lot more code in order to to scale.
"Yet other agile principles suggest the opposite, as in YAGNI and DoTheSimplestThingThatCouldPossiblyWork."
My concern with the premise of this article is that some might use it as a license for sloppy code. YAGNI and DoTheSimplestThingThatCouldPossiblyWork can be accomplished with code that is concise and clearly expresses intent. In fact, you could argue that these principles demand such code. I've seen a lot of code with many lines that accomplish very little, and that kind of "technical debt" never pays off, in my experience.
Of course, cutting corners isn't the only kind of code debt, and the author makes some good points. If you're spiking something or prototyping it, and intend to rewrite or throw away, technical debt might be a good tradeoff.
I also take issue with this:
Early on at IMVU, we incorporated in tons of open source projects. This was a huge win... The downside was that we had to combine dozens of projects whose internal architectures, coding styles, and general quality varied widely. It took us a long time to pay off all the debt that incurred – but it was worth it.
The more you can offload to open source libraries or third party APIs, the less your application has to do, and the less you have to maintain. If the library or API sucks, then sure - you're incurring technical debt. But if the library/API is good, or you can contribute to make it good, then it's a win all around.
Early on at IMVU, we incorporated in tons of open source projects. This was a huge win... The downside was that we had to combine dozens of projects whose internal architectures, coding styles, and general quality varied widely. It took us a long time to pay off all the debt that incurred – but it was worth it.
I think that's more or less exactly the point he makes. Some external dependencies are good, some are dreadful. At some point, you need to address the bad ones.
I tell my clients that cutting corners is "an hour of savings today, 5 hours of cost tomorrow".
Re: cutting corners, it really depends what you mean by "cutting corners". There's a whole continuum of code quality from "omg this sucks I want to kill the person who wrote it" to "this is the most beautiful piece of code every designed by man. Anything short of the latter is effectively incurring debt. I don't think Eric Ries is advocating dirty, nasty coding. Instead, I'd say he's suggesting that you should be comfortable with not writing the best possible code, rather than always feel like you're not doing well enough.
The trick isn't in reducing code quality to save time. The trick is simplicity. Too often developers equate quality and complexity; the two are orthogonal.
A simple architecture with high-quality code will take far less effort to maintain than a complex architecture with high-quality code OR a simple architecture with low-quality code.
In my experience, the vast majority of the technical debt I've seen has resulted from building complex solutions to simple problems.
Keeping the solutions as simple as possible to fit the needs of the project is a very good way to keep down technical debt AND facilitate rapid development.
A common theme in the comments to that story was that there are costs associated with loose coupling. Not making loose coupling a first priority means that one will incur some technical debt; but given that one gets something that will work sooner, this is often a good call.
Does anyone know of any software teams that explicitly talk about their technical debts and that have plans for "downpayments"?
There are then per-application technical debt pages for specific details on our "portfolio" of debt. (We're also a fair bit larger than most startup dev teams, so having this level of formalism is more appropriate in our case than say just a whiteboard somewhere...)
We don't do anything magical; there is no secret sauce, noe no spreadsheets with formulae or anything fancy; it's literally just a series of wiki articles and Jira tickets with issue type "Debt" so we can easily find the documented debt and make plans when/whether to retire it.
So the concrete formal mechanism is "use your bug tracking system and flag them somehow so you can filter/search for them."
I will add some additional links that our top-level debt page references as useful:
http://chrissterling.gettingagile.com/2008/10/20/managing-so...
http://enterprisearchitect.typepad.com/ea/2008/10/watch-your...
http://www.youtube.com/watch?v=pqeJFYwnkjE (Video: Ward Cunningham on technical debt)
...I've tried in the past to explain this to others using retail "shrink" as an analogy. For those unfamiliar with the term, as I know it, the idea is that you assume a certain percentage of loss (in my experience, as shoplifting in a music store) and by writing that off, it allows you to focus your energies where they have more impact on profit. For example, placing the lowest-margin items in the most vulnerable parts of the store to deter theft of items where you really make money.
I'm glad someone took the time to write up a better explanation that I can now refer to.