The Software Architecture Manifesto
Based on my experience, I came to define the next manifesto that reminds me what the spirit of architecture should be.
Every time I’m in doubt whether I’m building a robust solution or if I’m on the scope-creep zone, I check the manifesto to make sure I don’t over-engineer a solution. Here’s the manifesto:
- An architecture must serve a purpose, not a purpose the architecture.
- An architecture is an anchor, not a locker.
- An architecture should be concrete enough to facilitate re-usability, but abstract enough to facilitate adaptability.
- An architecture won’t fix a broken process nor a broken infrastructure.
- Strive for Conceptual Integrity.
- Make it fault-tolerant.
- There’s no silver bullet.
Let me describe each one of these.
An architecture must serve a purpose, not a purpose the architecture. I’ve seen tons of systems to fail just simply because some architects decided to force everyone to use one single architecture model/framework for all systems and for all teams within an organization. They made everyone to change their business and system purposes (and even their existence reason) just to fit the constrained architecture, causing all kind of long-term issues because the system never met all requirements either effectively or efficiently. For example, you might want to create an incredibly intuitive app, but your company might impose using a “UI framework that has worked well for the past 15 years” that would supposedly help on quickly creating visual apps but, at the same time, the UX is barely usable since such framework does not support modern capabilities (like drag and drop, multi-touch events, etc.), crippling thus the entire purpose of some tools that were originally developed with the intention of allowing efficient operations, cost-reduction on training materials, quick adoption, etc. And, sadly, at the end of the day, the purpose of the tool was defeated by the imposed architecture.
An architecture is an anchor, not a locker. This one stuck in my mind when I heard it from SuZ Miller (from Software Engineering Institute) during a conference. Basically, an architecture exists to govern the overall consistency on your system and layers interactions; but it should not become a locker that prevents you from being productive or that dooms your project to failure due lack of flexibility. Your architecture should dictate guidelines, and constrain vital features, but never be an inflexible box.
An architecture should be concrete enough to facilitate re-usability, but abstract enough to facilitate adaptability. If you must provide an architecture, make sure you design it in a way that other developers can reuse the components, but leave it abstract enough so that the developers can fill the gaps each system needs for its own purposes. In this case, “abstract” does not necessarily refer to “abstract classes” in code: you could simply choose to document which layers should be defined by each system and let the implementors to decide how to handle that. For example, should a reusable architecture for your team’s web apps include code to enforce how to validate authorization for all downloads, or should it leave that responsibility to each web app’s needs? Should it force how to handle logging, or it let each app to define how and where to create the logs? Should it rely on some core-tables that must exist on all DBs to work, or it should it allow defining its own DB-schema? The more aspects you attempt to cover in your so-called reusable architecture, the more chances you’ll find hard to implement unique features on each app without breaking other apps, and the more chances you’ll have to patch your architecture until it becomes a Frankenstein (well, the monster that Dr. Frankenstein created).
An architecture won’t fix a broken process nor a broken infrastructure. It doesn’t matter how good your architecture is, issues will continue emerging if your business processes are broken. Fix your processes first, then design your architecture. Same thing applies to bad infrastructures: Your architecture might be flawless, but your app won’t even work if your infrastructure is all broken.
Strive for Conceptual Integrity. This is a term that Fred Brooks explained on his Mythical Man-Month book. When you take an existent [well-written] system, make sure that you understand what’s the conceptual architecture is and follow that path. You can add or improve features that clearly fits with the overall system design (and/or purpose); similar thing applies when designing a new system: make sure your backlog items (and/or list of functional requirements) are aligned with the key purpose of the system. Additionally, actual implementation code should attempt to follow the current design so the code doesn’t become a parade of design patterns.
Make it fault-tolerant. This quality attribute is probably one, if not the most, important piece of any modern enterprise software system and needs its own post. Still, I’ll summarize it for the sake of keeping the manifesto useful. Your architecture must be fault-tolerant enough so that common infrastructure glitches, human errors and data-integrity issues doesn’t translate directly to global-wide fatal failures. For example, shall your system allow an admin making system-wide changes, it should be designed in a way that prevents that a distracted admin doesn’t jeopardize the entire operation of your company due a simple user-input-error. Some failures are expected to happen, such as power-outage or network disconnections, so keep those in mind when designing critical systems and need to recover gracefully from them.
There’s no silver bullet. Another concept that Fred Brooks talked about on his book. The book basically says “there is no single development, in either technology or management technique, which by itself promises even one order of magnitude [tenfold] improvement within a decade in productivity, in reliability, in simplicity”. As consequence, don’t expect to design an architecture that will solve the world. Attempting to do so will only make you and your team waste time, and you will end-up anyway with an architecture that will not cover every possible requirement your team will ever need.
Keep the manifesto present when designing an architecture. The whole point is that you can deliver your project on time and keep scaling-up your architecture on future iterations, all that without committing the mistake of becoming an astronaut architect or delivering a scoped-creep solution.