One fundamental feature of programming (development, software engineering, whatever the name), is that you have to face the unknown.<p>If you already knew what problems lie ahead and their solution, you would already have programmed it, and then what use would it be to rewrite the program? Just re-use the previously written code!<p>So by definition, what you will develop, will be a program solving a problem with unknown dimensions and solution. You start by writing the code for the known parts, but while doing that, you have to live with the fear of the unknown that lies beyond the next procedure.<p>Performing specifications and analysis phases is a way to deal with this fear of the unknown, by drawing a coarse map. But often it's not possible to precise the map much better than labelling "Here be dragons" ahead (or worse, to hide the dragons with reassuring words, like Module X, or Component Y).<p>So be courrageous, plow ahead, and you'll be lucky, when you'll get close, you'll see that what you thought to be dragons was just a hill, and you'll find a solution to climb or circumvent it.<p>What you need to learn however, is how to deal with the complexity that emerges from discovering problems and solutions as you go: then you have to step back a little, and find simplifying abstractions, to refactor the work done so far, to get a simplier solution englobing all the problems seen so far, (and hopefully that will be found in the future).