A project I’ve been working on launched recently. Well, re-launched. A slick little iPhone app called Postography, which lets you send postcards with messages and pictures from your iPhone. Nifty, but sounds fairly straightforward, right? An app that shouldn’t have taken too much time to build.
Unfortunately, we didn’t build it; we rebuilt it. And the company that took the first crack at it (naming no names here) did a fairly good job on the server side…but epically botched the initial version of the app itself. Oh, it ultimately sort of kind of worked, other than the many bugs and frequent crashes. But quite aside from those, its codebase was such a festering abyss of global variables, spaghetti code, hacks, no-ops and race conditions that extending it or changing it at all was next to impossible without major reconstructive surgery.
This happens a lot more than anyone would like to admit. Behind the shiny UI of many applications there lurk Lovecraftian architectural nightmares that challenge the very sanity of anyone charged with maintaining them or adding features. Ask a developer, any developer; they’ll have some horrific tales to tell.
And if yours is one of those–if your company is an app, and that app works, but doesn’t work cleanly, or elegantly, or extensibly, or scalably–then your company has already racked up a pile of technical debt, and whether you know it yet or not, you’re already in big trouble.
I like to use a housing metaphor: just because your house looks good, and its rooms are comfortable and well-decorated, doesn’t mean it isn’t built on such a poor foundation that it may collapse if a heavyset guest so much as runs down the stairs. Add another story? Are you kidding? Forget about it. Indeed, your house may have been built on poor ground to begin with, in which case not even a new foundation will do: you have to scrap it entirely and start again somewhere else.
This happens even at extremely technical companies. I give you RIM as an example. Remember when they released a tablet without an email app? Remember how they silently treaded water for an apparent eternity while iOS and Android left BlackBerry in their wake? These debacles were not design choices or deliberate executive decisions. They happened because RIM had run up an enormous amount of technical debt, and it took them years to pay it off.
Like monetary debt, technical debt is perfectly OK as long as a) you don’t accrue too much of it and b) you know all about it. Of course there are often compromises to be made between, for instance, scalability and speed of development. Of course when a deadline is approaching, and/or the funding is running low, and the task seems immense, the quick-hack shortcut is sometimes the right choice. Of course all developers are understandably biased towards the tools they know–or, sometimes, the tools they want to learn–rather than the one that’s ideal for the job at hand.
But all too often the accumulation of technical debt in favor of short-term success is ultimately a terrible mistake. Like all debt, technical debt compounds with time. Worse yet, many non-technical people — i.e. too many managers, executives, and founders — tend to underestimate its danger, or fail to even realize when they’re running it up by the vault load…until they find themselves spending many months fighting to pay off their technical debt while their competitors are happily zooming ahead. Just like RIM.
So how can startups avoid such an awful fate?
Hiring the right people is critically important, of course. Pair programming helps, as does the primary/secondary model I favor. And I’ve long thought that technical assessments would be a good idea: have a few experienced people take a week or so to audit your code and architecture, once early in the application’s lifecycle and once more midway through. The company I work for has done that once or twice, but alas, it’s not really common industry practice, or at least not yet.
What can you do if you’ve already run up a load of technical debt? First, get your head out of the sand and accept that you have a major problem. Second, stop digging. Stop adding new features, and get things into a semi-stable state so that you can see what you do and don’t have. Then try to determine whether you can keep your metaphorical house, but need to rebuild the foundation — even though things that previously worked will start to break again while that repair is underway, which is always frustrating — or whether you have to throw it all out and start again. (Which can be both the best solution and the fastest one.)
Most of all, though, listen to your developers. If you’ve hired the right people, then they want clean, extensible, scalable code as much as you do. It was almost painful looking through the initial source code of the Postography app. Now I feel a bit like we performed surgery that saved the life of a dreadful-car-accident victim who has gone on to become an Olympic athlete. It’s never too late to rescue your app; but the earlier you start, the easier it gets.