There's a wide spectrum between specs upfront vs trial and error with the codebase. Somewhere in the middle sits the whole MVP and iterative building, where you start with a smaller codebase and fill it up. Basically exploiting the fact that a lot of concepts, while interconnected, are modular and can be tackled on their own. Like how the design of the brakes and the engine in a car, while related, are mostly blackboxes in regard to each other.
People that do trial and errors lacks direction and their code is often fragile, especially with evolving situation. Because their have failed to grasp the deeper truth of the domain. The usual signs are tightly coupled code and code churn.