Among the software architects with a strong voice on conferences, twitter and in the blogosphere there is wide spread agreement that one should bet on evolutionary architecture.
The idea behind an evolutionary architecture is that you make decision as late as possible and responsible. Instead of dreaming up a detailed architecture up front you only decide on the parts immediately needed. The point is that this allows you to start earlier to produce actual software because you don't have to wait two weeks for the architect to finish her UML diagrams. This allows to actually deploy software and get feedback from the users, which is pretty much the basis for all things agile. It also helps to avoid the fallacy of over designing and regulating stuff that is actually irrelevant for the application, also known as YAGNI: You ain't gonna need it.
I try to follow this approach. I have a hard time to imagine anything else to work. Maybe there are people out there that can simulate the result of 10 developers working for a year in their head and based on that make the proper decision up front. I'm certainly not that kidn of super hero.
But the world is not perfect. I experienced in multiple cases a situation as the following: I sit together with a developer to code a part of a system that is kind of different then everything else done so far. Maybe the first form of the project, or the first interface to another system. So there is plenty of space for some architecture decisions. We put some down in code, the once we actually need right now. Since we know this code is going to be a template we actually put a little extra effort in to make some decision more obvious. Maybe through comments, maybe through making the code extra clean. Other decisions we more or less consiously put back because we don't have enough information.
Then time goes by.
When I come back to the code, or to places where it got used, or places where the approach was copied to I often find ...
... a mess.
The frustrating part is: It is my own mess. While my fellow developers used the code we wrote as a base for their own work. they used and amplified everything they found. The good parts as well as the bad parts. And while the good parts are hardly noticed (thats after all how good code should behave: just working away without drawing attention) the bad part stick out like a sore thumb. Actually in many cases the sore thumb stuck out for a long time without anybody (or at least without me) noticing until it got caught in door and prevents the door from closing in a very painfull way.
So while code got used and reused in some way a design decision was necessary. But since the one primarly responsible for such decisions didn't noticed it wasn't made at all, or it was made in an inappropiate way, often without even noticing that a decision was being made.
I love (to write) blog posts that describe an important, serious problem and then provide a nice clean solution to it. Unfortunatly this isn't one of that kind. I have no solution to the problem. All I can come up with is: Write cleaner code. Coach the team to at least identify design challanges before they turn into problems. Do code reviews.
But if you have a better idea. Let me know.