Now I could have spent that time "whiteboarding" and it's possible I would have come close to the same solution. But whiteboarding in my mind is still guessing, anticipating - coding is of course real.
I think that as you gain experience as a programmer you are able to intuit the right way to begin to code a problem, the iterating is still there but more incremental.
An experienced programmer is also more cognizant of the importance of architectural decisions, hitting the balance between keeping things simple vs abstractions and the balance between making things flexible vs YAGNI.
Once those important bits are taken care of, rest of it is more or less personal style.
I never hold all the code designed in my head at once, but it's more like multiple linked thoughts. One idea for the overall structure composed of multiple smaller pieces, then the smaller pieces each have their own design that I can individually hold in my head. Often recursively down, depending on how big the given project is and how much it naturally breaks down. There's certainly unknowns or bugs as I go, but it's usually more like handling an edge case than anything wrong with the design that ends in a rewrite.
I wanted to work that way, when I was younger, but the results were seldom good.
Good judgment comes from experience. Experience comes from bad judgment.
-Attributed to Nasrudin
Apparently this quote has been attributed to an Uncle Zeke :) [0]
One of my "go-tos" from him, is the Smoke Seller[1]. I think that story applies to the Tech Scene.
I first heard the GC quote as attributed to Will Rogers, then, to Rita Mae Brown.
[0] https://en.wikipedia.org/wiki/Nasreddin
[1] https://www.tell-a-tale.com/nasreddin-hodja-story-smoke-sell...
My only optimization of this process is to use Java and not just throw out everything, but keep refactoring. Idea allows for very quick and safe refactoring cycles, so I can iterate on overall architecture or any selected components.
I really envy on people who can get it right first time. I just can't, despite having 20 years of programming under my seat. And when time is tight and I need to accept obviously bad design, that what makes me burning out.
Good design evolves from knowing the problem space.
Until you've explored it you don't know it.
I've seen some really good systems that have been built in one shot. They were all ground up rewrites of other very well known but fatally flawed systems.
And even then, within them, much of the architecture had to be reworked or also had some other trade off that had to be made.
I get a general idea, then start writing code; usually the "sticky" parts, where I anticipate the highest likelihood of trouble.
I've learned that I can't anticipate all the problems, and I really need to encounter them in practice.
This method often means that I need to throw out a lot of work.
I seldom write stuff down[0], until I know that I'm on the right track, which reduces what I call "Concrete Galoshes."[1]
[0] https://littlegreenviper.com/miscellany/evolutionary-design-...
[1] https://littlegreenviper.com/miscellany/concrete-galoshes/