Wednesday, October 28, 2009

Foreword


Foreword


The
challenges of developing high-performance, high-reliability,
and high-quality software systems are too much for ad
hoc and informal engineering techniques that might have worked in the past on
less demanding systems. The complexity of our systems has risen to the point
where we can no longer cope without developing and maintaining a single
overarching architecture that ties the system into a coherent whole and avoids
piecemeal implementation, which causes testing and integration failures.


But building an architecture is a
complex task. Examples are hard to come by, due to either proprietary concerns
or the opposite, a need to "sell" a particular architectural style into a wide
range of environments, some of which are inappropriate. And architectures are
big, which makes them difficult to capture and describe without overwhelming the
reader.


Yet beautiful architectures
exhibit a few universal principles, some of which I outline here:





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.


As you read this book, ably assembled and
introduced by Diomidis Spinellis and Georgios Gousios, you might look for these
principles and consider their implications, using the specific examples
presented in each chapter. You might also look for violations of these
principles and ask whether the architecture is thus ugly or whether some higher
principle is involved.


During the development of this
Foreword, your authors asked me if I might say a few words about how someone
becomes a good architect. I laughed. If we only knew that.... But then I
recalled from my own experience that there is a powerful, if nonanalytic, way of
becoming a beautiful architect. That way[1]
is never to believe that the last system you built is the only way to build
systems, and to seek out many examples of different ways of solving the same
type of problem. The example beautiful architectures presented in this book are
a step forward in helping you meet that goal.



[1] Or exercise more and eat less.


 


No comments: