After programming for a few years, you probably know the feeling of going into "the flow". Basic things have become easy. Starting up a project has become routine. Fixing a bug follows the same process every time. So, setting up and working on something you haven't done before isn't that hard either, right? You can just lean back, trust your experience and start typing code right away until the whole project is done. Right? No. If only it would have been that easy...
I was falling into the above a while ago. But, just after starting on something without thinking it through in advance I learned that this was definitely not the right way to go. Whenever you start coding, things might seem easy and it might feel like you're on the right path, but the further you're advancing, the more clear it will be that planning and thinking about things upfront would have been a better idea. Starting something and not thinking about the consequences of your actions will surely lead to a coding hell that's hard to step out from.
So, what exactly do I mean with planning upfront? Do you need to draw out entire frameworks and think of all possible scenarios when adding a very small feature to an already existing product? No, I don't think so. At least, I think the level of detail and upfront planning you need to do grows with the size of a project. Fixing a bug always follows the same kind of structure, which you certainly don't have to draw out entirely every time you do it. Adding a new, small feature probably requires some more pre-coding work, but certainly not as much as a full-blown system setup.
What helps me when I start working on a new feature, is laying out the code paths upfront. Either on paper (just draw out the scenarios and eventually the framework that you're going to build) or directly in code (creating stubs, yet-to-be implemented classes based on interfaces, etc.). Just laying out the basic structure for a feature already helps out big-time and will prevent you from making basic mistakes that will cost you at a a later stage. How much work you exactly need to put into a new feature upfront is something you will find out by doing. If you plan out a new feature and get stuck at some later stage, you know that you didn't spend enough time upfront. If a feature was build successfully and you think you might have spent a little too much time upfront, just try to spent less the next time you're developing a similar feature. As always, getting your feet wet and trying things is the best way to learn. It's a very true cliché.