I don't know--my impression is that most people go to far in the other direction. They write code with no thought at all for the future, and then shortly have nightmarish debugging sessions in spaghetti code that's impossible to extend or reuse. All in the name of a rather extreme "worse is better" philosophy.

I've certainly experienced this with some of the people I worked with recently. Anything you win in the short term gets lost several weeks--if not days--later when everything is a horrible mess. Don't even think about coming back to that code months later!

I've found that putting in a little bit of care for the future pays off even in the short term. Perhaps not on the scale of hours or days, but definitely weeks. Which is still pretty immediate.

However, how you do this is also very important. The handy rule I've been using is simple: simplicity. Improve your code by making it do less not more. If you can make code more maitainable or general by simplifying, do it. If it would require adding new concepts or mental overhead, reconsider. Try to reuse existing abstractions as much as possible.

This usually--but not always--means making your code more functional. Do you really need to write this operation in place? Do you really need to tie everything together with a bunch of implicit state changes? Probably not! This is not to say that you should never use state: just be sure to only use it when it fits well and makes sense. And be explicit about it.

The functional style (at least in languages like Haskell) also lends itself very well to reusing simple and general abstractions. The key idea here is that these abstractions are not about doing more: they're about doing less. More general code simply leaves you less room to make mistakes. If you're working with lists of numbers, there are all sorts of arithmetic mistakes you can make; if you manage to write the same code against lists of anything, the only mistakes possible will be in list handling.

Haskell just makes this more practical by providing abstractions with a great "power-to-weight ratio": ones that manage to be simple, general and yet still expressive. Code with functors or monoids or traversables is easier to write than more concrete code and yet still flexible enough for many useful tasks. As a bonus, it's also more reusable. For free.

So the key idea is reduction: all these abstractions work by stripping concrete types of power. A functor can do much less than a list. A monoid can do much less than a number. This lets you write nicer code without becoming an "architecture astronaut" because instead of adding structure, you're really taking it away.

I've found that programming like this really helps in maintaining and extending the code later on. But it doesn't slow me down when I'm writing either--I actually save time because I spend less getting time getting the code correct in the first place.

These days, I've started being able to make large changes or add complicated features and have them work on the first try. Not every time, but surprisingly often. Certainly much more often than before! In large part, I think this is because of writing the code with an eye towards simplicity.

So the important insight: take the simple route, not the easy route.