I'm a big believer of designing for the problem at hand and not blowing out your design by trying to guess all the cases that you have to cater for because "someday we might need it".
Basically, given a list of specific requirements, design against that, however, this does not mean that you shouldn't:
- make aspects of your design configurable rather than hard coding those aspects in your solution. Either via parameters passed at runtime or via an external config read at startup (or after HUP'ing).
- lace your code with magic numbers,
- avoid having a look to see if there is something already written that you can reuse, maybe after adapting the existing solution to provide an approach that is suitable for the existing situation as well as for the new requirement(s).
The main problem with designing for "possible futures" is that you are always just guessing. Possibly making educated guesses, but "when push comes to shove" it's still just a series of guesses.
By doing this you also have the very real possibility of squeezing your solution to fit the general case(s) rather than solve the specific problem at hand as defined by your known requirement(s).
What's that saying? "When all you have is a hammer, everything begins to look like a nail."
I wish I had a pound for every time I've heard someone say, "But it's a solution that's more adaptable for those general cases we might see in the future."