The best defense against this that I've found is to ensure, as much as possible, that interfaces can be replaced. The single responsibility and interface segregation principles can help here. Using small, focused interfaces and letting modules implement more than one of them makes it easier to use the strangler pattern to replace interfaces that no longer work well with new and improved ones.
Also avoid temporal coupling as much as is feasible. Unnecessary statefulness is the easiest way to make this sort of thing harder than it needs to be.
> 2. . To design a spacecraft right takes an infinite amount of effort. This is why it's a good idea to design them to operate when some things are wrong .
> 3. Design is an iterative process. The necessary number of iterations is one more than the number you have currently done. This is true at any point in time.
> 4. Your best design efforts will inevitably wind up being useless in the final design. Learn to live with the disappointment.
Also 9 10, 11, 12, 13, 14 and a bunch of the others apply too.
An excellent interface will eventually be deformed beyond recognition chasing the architectural dragon; a well-crafted library will outlive the project.
Much of the system can be complete like this with forethought. The pieces that cannot can be factored out to the edges.
The majority of devs generally are happy to tack on their features and PRs to whatever random scaffolding they can, without regard or awareness for how their individual component fits into the larger system, or how it may be extended. And to be honest it’s not necessarily a bad thing, because they do need to get work done, and merging PRs shouldn’t be reserved for the enlightened.
I guess I’m just pessimistic. The reason we don’t see perfect software is because we are not capable of producing it. At a certain point it all becomes spaghetti. If you work with software that isn’t spaghetti, it’s only because the people who care about it not becoming spaghetti haven’t left yet. This is good, but eventually they will leave, standards will decline, and you will become one with the pasta.
Forethought is only possible if people tell you the requirements precisely correctly upfront. Real systems design is you get 90% built and someone drops a hard requirement that's also a layering violation on you.
Math arises from first principles, human behavior does not.