Future creep is not about adding features to your products. At least, it is not directly about that. Rather, it is about adding infrastructure to your products in preparation for features that may or may not be added later. In the future.
This is really subtle, because it can happen even (or perhaps especially) when the feature list for a product has been frozen. So, sure, you can’t add any more new features for this release, but there has been talk about some new feature X being added eventually, and if you just tweak the code a bit here and here, and maybe there, the way can be paved for X that much more easily!
That feature X can be anything: a programmer interface (API), a drag-and-drop UI, element categorization, data export/import, batch processing, anything at all, anything that you don’t intend to implement immediately, but which has been bandied about as a possible addition someday.
Paving the way doesn’t sound bad at all, though, does it? In fact, it sounds proactive and laudable. And if that feature X goes through in a timely fashion, exactly as you envisioned, I’m sure you’ll be praised for your foresight.
Even the simplest of potential features can be implemented in a number of ways. Or not implemented at all. At best, your “foresight” can result in wasted time, where you spun your wheels for a few hours (or days!) playing “what if” and “let’s pretend”, trying with too little information to think of how best to architect your code to accommodate that future feature.
Worse, it could result in dead code, smelly sections of your application that no one is going to have the time to clean up, and which will remain for years until no one working on the code even remembers why it is there. Which means they are unlikely to remove it, because why remove something that obviously isn’t affecting the app?
At worst, though, what seemed like a good idea at the time can make things actively worse down the road. It might get in the way of how the feature will actually be implemented, or prevent some other feature from being added cleanly.
The solution? It consists of three parts:
First, never implement more than you need to. That sounds harsh, in a grasshopper-and-the-ant kind of way, except it really isn’t. It isn’t a mandate to slack off, it’s a command to do what you know. Implement the feature you’re working on, not the feature you hope will land someday. Keep it simple, keep it minimal, and keep it real.
Second, never plan further than you can see. Yeah, that new feature might land next month. In fact, people may be talking about it as if it were a dead certainty. But the future can change, and it can change dizzyingly fast. Unless a feature is actually part of the next release, don’t implement it. This certainly isn’t saying you shouldn’t be proactive; you should just restrict your proactivity to items that aren’t pretend!
Third, don’t be afraid of imaginary work. That work you think of when someone says some feature might be implemented someday? Yeah, that’s imaginary work. If you’re perfectly honest with yourself, you’ll admit that you really don’t know what the feature will entail. Often, what you think will require a pile of work turns out to have a simple solution. (And, frankly, vice versa.) Regardless, wait until you have the information you need to do a project right. Don’t let your fear of imaginary work drive you to imaginary solutions.
It is so easy to fall into this trap, since it runs under the heading of “saving myself work down the road.” Except it doesn’t really save you work, and it can even result in more work. Beware future creep!
This is all related to a RubyConf presentation I’ll be giving in Orlando on November 5th, entitled Recovering from Enterprise: how to embrace Ruby’s idioms and say goodbye to bad habits. If you’re going to be there, do stop by and introduce yourself!