There is always a tension in programming, between the desire to do things the elegant way, and to do them the lazy way. Elegant programming is largely a matter of managing complexity, writing things in such a way that the code structure will scale nicely to more complex problems, even if it involves more of an up-front cost.
The Lazy Way
Programmers who always do things the lazy way quickly hit walls as the complexity of their programs grow. This is because patterns which work for simple programs will often not work effectively for larger ones. Also, when starting off or writing small programs, it is tempting to mix different logics together, since they are often simple enough that they can be understood without trouble. This makes for very fast coding, but ends up causing hopeless complexity as the program grows, requiring major re-design. At the point where you end up re-structuring the project, the initial experience means that you are more likely to know what design is most appropriate, but the transition cost will be greater as you will have an existing code base to transform.
The Elegant Way
On the other hand, programmers who obsess over doing things the elegant way end up spending all their time designing systems, delaying the process of actually making things. This involves a higher up-front cost, but hopefully saves time in the long run, as there will be less of a need for re-design later on. This sounds nice in theory, but unfortunately doesn’t always fly in practice. The eventual requirements of a program’s design are rarely known in advance, and often as the project grows the established design becomes less and less appropriate. This may end up requiring the same kind of re-design you hoped to avoid.
If you can’t eliminate the possibility of re-design, maybe another approach should be taken. Having a good idea of how the program will scale is still critical, but instead of choosing one design and diving into it, simply be aware of how you intend the program to grow. Just keeping this in mind will help you write code which suits this design. When the time comes that you need the scalability the design provides, changing your code to follow it will be much easier, since you have subconsciously (or consciously) avoided doing things which conflict with it. Instead of trying to prevent re-design, you try and reduce its eventual cost. In the lucky case, you may end up not needing to make this transition at all!
This technique tries to find a compromise between doing things the elegant way, and doing them the lazy way. Finding the right balance will depend on the needs of the project you are working on: what is its purpose, how large it may grow, how critical it is that it works reliably, and how important it is that it is finished quickly. Regardless, being stuck on one end of the spectrum is not somewhere you should be unless you have an explicit reason.