Last week, we discussed coding for tomorrow – the concept of writing code not for the current moment, but instead for the moment six months down the road when you have to crack that code back open and figure out it works.
Ward Cunningham has come up with the perfect metaphor: “technical debt.”
You have a piece of functionality that you need to add to your system. You see two ways to do it, one is quick to do but is messy – you are sure that it will make further changes harder in the future. The other results in a cleaner design, but will take longer to put in place.
[...] doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into the better design. Although it costs to pay down the principal, we gain by reduced interest payments in the future.
Jeff Atwood adds something utterly critical:
[...] accumulated technical debt becomes a major disincentive to work on a project. It’s a collection of small but annoying things that you have to deal with every time you sit down to write code. But it’s exactly these small annoyances, this sand grinding away in the gears of your workday, that eventually causes you to stop enjoying the project
In this sense, it can be fatal. I have a couple clients with codebases so messy that unless I can pay down some of their technical debt, I really hate working on it.
So, how do you not get there? I don’t know if it can be avoided. Jeff also says:
[...] it’s impossible to predict exactly how those key decisions you made early on in the project are going to play out. All you can do is roll with the punches, and budget some time into the schedule to periodically pay down your technical debt.
It’s true. It’s tough to predict everything, especially with a client that pushes and pushes and pushes small changes. Here’s an example, with some ideas for staying as debt-free as you can —
We have a client with a complex site based on eZ publish. It’s the most hod-rodded eZ install we’ve ever done (and believe me – we’ve done some batsh*t insane things with eZ over the years). The client is very active, full of ideas, and they keep coming with idea after idea. The current trend is on Salesforce integration, and we’re really in deep with it right now.
I was talking with Sam the other day about the incremental nature of the site. How do you manage it? Sam called it “creeping elegance,” which I re-ordered to “elegance creep.” That’s what you call feature creep done well, I guess – elegance creep.
How have we kept this situation thusfar under control? A few methods —
First, don’t implement right away, if you can help it. When they come back with a new idea, step back, elevate yourself to 50,000 feet, and try to see where the puzzle fits in the big picture.
Second, if the puzzle piece doesn’t fit at that moment, start writing a larger framework in your head. Keep some idea in your head of the larger structure in which this piece would fit, and then look for the tipping point where you can create this larger construct and back-port the appropriate features.
Back to my example, my client keeps pushing the Salesforce integration. We added one thing, then two, then three. For each one, we had to create new content attributes. Each time we did this, I keep turning the situation over and over in my head, thinking, “To do this right, we need to do X. And this fits with Y, then Z.”
Just last week, I told the client that we had to step back and refine a bit. So, this week, we’re going to write a custom datatype that encompasses all these attributes in a more elegant way. Then we’re going to bite the bullet and back-port the existing feature set.
Third, watch the quality of inidividual code, which goes back to our previous discussion. Whenever you finish a feature, go back through it, and fix stuff. You know there’s kludge in there. Move literals out to config files, abstract stuff, centralize code, make sure you didn’t repeat yourself, etc. If you don’t do this, kludge will accumulate. Kruft will pile up. Unless you keep it under control, it will control you.