A student had been sitting motionless behind his computer for hours,
frowning darkly. He was trying to write a beautiful solution to a
difficult problem, but could not find the right approach. Fu-Tzu hit
him on the back of his head and shouted 'Type something!' The student
started writing an ugly solution. After he had finished, he suddenly
understood the beautiful solution.
-- taken from http://eloquentjavascript.net/chapter6.html
I took a similar path to what you are describing when I began learning software development, and I also read about how important upstream design is to a project. I tried and tried for 2 years to completely design a program before building it, and every time I failed. Things never really worked out according to the assumptions I made in my designs. Adding to my high failure rate was the fact that I would often change my requirements in the middle of software construction, making the design invalid.
I recently began using a better approach with much more success (and more fun too). The basic idea is to create working versions of your program in very short iterative periods (agile development). It is very likely that your first whack at a new feature is going to be ugly, but then you get it built, and come back to it later, making it more elegant because your thoroughly understand it the second time around. So instead of rewriting my projects over and over again, I now just refactor the code whenever I revisit it. It is a much more rewarding experience.