The first step is admitting that you can't optimize for every direction. Facebook has a motto, "Done is better than perfect," which I used to think was cheesy, but realized is quite brilliant. "Perfect" leads to satisfaction, but "done" leads to revenue.
Say you want to try alternative payment processing methods on your site. Your site it tightly integrated with PayPal, and you want to add Stripe. You could (A) spend 1 day to bolt on Stripe with a hack in the HTML, (B) spend 4 days and add enough views to the frontend to make Strip work in a non-disgusting manner, or (C) spend two weeks and refactor the entire backend with a generic interface that will handle an infinite number of payment solutions.
All three lead to success, but you can't optimize for both time and perfection. Set a time budget. Leave breadcrumbs for the next programmer. Instill a culture that says, "Our code isn't perfect, we know this, but we do what we can with what we have." Done is better than perfect.
Although I agree with your idea in principle, there are only so many times you can just hack something on top before you start to wonder if the refactoring technique is actually the better way to go. You could just end up with a hacky system held together with sticky tape.
With forethought, you should have built your system originally with method C in mind. If he had done this at the beginning instead of just hacking it together then all this work after wouldn't have been needed!
1) Apply conscious planning and forethought. Some things are clearly going to be used a lot, some things might not. Use bolt-on hacks where appropriate, invest time for things you expect to be using forever.
2) When the longevity of the tool is not easy to pin down, test it out with a hack. Spend 1 day adding Stripe the hacky way, and keep a slushbucket of time budgeted for revisiting experimental hacks that look like they will last a while.
That's my general approach, anyway. Most of the time, a hack is good enough and anything more is a waste of time. The story is admittedly a little different for me though; for me, software is a tool to do my job- software is not my job.
I think I see it differently as we have just spent 3 years developing a CMS at our company and every decision has been a well thought out and concious one. We spent 3 weeks planning when we first conceived the plan.
We have only had to do 2 refactors in that time on 2 controls. That was more about understanding our customers needs more as we progressed rather than not enough planning though.
Previous to that I built a custom ecommerce site for a wholesale distributor. That whole process was more suited to a quick hack over a well thought out decision. That's why I say I agree in principle, so long as the project allows it.
Don't get suckered into premature optimization. If you're still small, bolting stripe on lets you accept money and get back to building the rest of the product. Sometime in the future it will make perfect sense to redo the entire payment system. Today is not that day.
"Done is better than perfect" is brilliant. It is motivational, succinct, and easy to believe. From my particularly context of a side project with no real deadlines, however, I can have perfect if I want to. There's no race against the clock, nobody to report to, nobody relying on my results -- just me and my idea.
At any rate, I'll tweak the "done-perfect" lever more towards done.
Whether you think there is a race against the clock or not, time passes regardless; your mind changes, your body ages, technologies change, people change. By the time you're done with your "perfect" creation, it will be too late to matter.
Until the last few years, I think I was of the mentality that would follow (C) or (B), but have recently switched to (A) -- just ship it and fix whatever's not perfect later; the opportunity cost of not shipping is too high.
Facebook's motto reminds me of something from a Holman slidedeck: "Nothing great was ever not shipped."
Say you want to try alternative payment processing methods on your site. Your site it tightly integrated with PayPal, and you want to add Stripe. You could (A) spend 1 day to bolt on Stripe with a hack in the HTML, (B) spend 4 days and add enough views to the frontend to make Strip work in a non-disgusting manner, or (C) spend two weeks and refactor the entire backend with a generic interface that will handle an infinite number of payment solutions.
All three lead to success, but you can't optimize for both time and perfection. Set a time budget. Leave breadcrumbs for the next programmer. Instill a culture that says, "Our code isn't perfect, we know this, but we do what we can with what we have." Done is better than perfect.