[摘]Some points in <Beautiful architecture>
Part Ⅰ- Universal principles in beautiful architectures:
- One fact in one place
Duplication leads to error, so it should be avoided. Each fact must be a single, nondecomposable unit, and each fact must be independent of all other facts. When change occurs, as it inevitably does, only one place need be modified. This principle is well known to database designers, and it has been formalized under the name of normalization. The principle also applies less formally to behavior, under the name factoring, such that common functionality is factored out into separate modules.
Beautiful architectures find ways to localize information and behavior. At runtime, this manifests as layering, the notion that a system may be factored into layers, each representing a layer of abstraction or domain.
- Automatic propagation
One fact in one place sounds good, but for efficiency's sake, some data or behavior is often duplicated. To maintain consistency and correctness, propagation of these facts must be carried out automatically at construction time.
Beautiful architectures are supported by construction tools that effect meta-programming, propagating one fact in one place into many places where they may be used efficiently.
- Architecture includes construction
An architecture must include not only the runtime system, but also how it is constructed. A focus solely on the runtime code is a recipe for deterioration of the architecture over time.
Beautiful architectures are reflective. Not only are they beautiful at runtime, but they are also beautiful at construction time, using the same data, functions, and techniques to build the system as those that are used at runtime.
- Minimize mechanisms
The best way to implement a given function varies case by case, but a beautiful architecture will not strive for "the best." There are, for example, many ways of storing data and searching it, but if the system can meet its performance requirements using one mechanism, there is less code to write, verify, maintain, and occupy memory.
Beautiful architectures employ a minimal set of mechanisms that satisfy the requirements of the whole. Finding "the best" in each case leads to proliferation of error-prone mechanisms, whereas adding mechanisms parsimoniously leads to smaller, faster, and more robust systems.
- Construct engines
If you wish to build brittle systems, follow Ivar Jacobson's advice and base your architecture on use cases and one function at a time (i.e., use "controller" objects). Extensible systems, on the other hand, rely on the construction of virtual machines—engines that are "programmed" by data provided by higher layers, and that implement multiple application functions at a time.
This principle appears in many guises. "Layering" of virtual machines goes back to Edsger Dijkstra. "Data-driven systems" provide engines that rely on coding invariants in the system, letting the data define the specific functionality in a particular case. These engines are highly reusable—and beautiful.
- O(G), the order of growth
Back in the day, we thought about the "order" of algorithms, analyzing the performance of sorting, say, in terms of the time it takes to sort a set of a certain number of elements. Whole books have been written on the subject.
The same applies for architecture. Polling, for example, works well for a small number of elements, but is a response-time disaster as the number of items increases. Organizing everything around interrupts or events works well until they all go off at once. Beautiful architectures consider the direction of likely growth and account for it.
- Resist entropy
Beautiful architectures establish a path of least resistance for maintenance that preserves the architecture over time and so slows the effects of the Law of System Entropy, which states that systems become more disorganized over time. Maintainers must internalize the architecture so that changes will be consistent with it and not increase system entropy.
One approach is the Agile concept of the Metaphor, which is a simple way to represent what the architecture is "like." Another is extensive documentation and threats of unemployment, though that seldom works for long. Usually, however, it generally means tools, especially for generating the system. A beautiful architecture must remain beautiful.
These principles are highly interrelated. One fact in one place can work only if you have automatic propagation, which in turn is effective when the architecture takes construction into account. Similarly, constructing engines and minimizing mechanisms support one fact in one place. Resisting entropy is a requirement for maintaining an architecture over time, and it relies on the architecture including construction and support for propagation. Moreover, a failure to consider the way in which a system will likely grow will cause the architecture to become unstable, and eventually fail under extreme but predictable circumstances. And combining minimal mechanisms with the notion of constructing engines means that beautiful architectures usually feature a limited set of patterns that enable construction of arbitrary system extensions, a kind of "expansion by pattern."
In short, beautiful architectures do more with less.
Part Ⅱ - From part Ⅰ, we summarize the architectural properties and structures:
Principle or property | The ability of an architecture to... |
---|---|
Versatility | ...offer "good enough" mechanisms to address a variety of problems with an economy of expression. |
Conceptual integrity | ...offer a single, optimal, nonredundant way for expressing the solution of a set of similar problems. |
Independently changeable | ...keep its elements isolated so as to minimize the number of changes required to accommodate changes. |
Automatic propagation | ...maintain consistency and correctness, by propagating changes in data or behavior across modules. |
Buildability | ...guide the software's consistent and correct construction. |
Growth accommodation | ...cater for likely growth. |
Entropy resistance | ...maintain order by accommodating, constraining, and isolating the effects of changes. |
Structure | A structure that... |
---|---|
Module | ...hides design or implementation decisions behind a stable interface. |
Dependency | ...organizes components along the way where one uses functionality of another. |
Process | ...encapsulates and isolates the runtime state of a module. |
Data access | ...compartmentalizes data, setting access rights to it. |