You have to "solve" the problem once in order to clearly define it and then solve it again create a solution that works.   

The finished software design should look well organized and clean, but the process used to develop the design isn't nearly as tidy as the end result. Design is a sloppy process, you take many false steps, and make a lot of mistakes while designing software. 

The purpose of design is to identify the mistakes early. It's cheaper to find mistakes during design phase and correct them, than having to correct implemented code. 

At the same time, until your software fails in production, you don't really know the true requirements. So it's a delicate balance of upfront design vs. on-demand design. 

An ideal program runs instantly, takes zero storage, use zero network bandwidth, doesn't have any errors, and costs nothing. In the real world, there are trade-offs. A good design should try to find a balance among various competing factors. 

A good design emerges out of the iterative process of thinking about the program, writing the program, and rewriting the program.