Software architecture has emerged as an important subdiscipline of software engineering, particularly in the realm of large-system development. Architecture, which is the prudent partitioning of a whole into parts, with specific relations among the parts, is what allows groups of peopleoften groups of groups of people separated by organizational, geographical, and even temporal boundariesto work cooperatively and productively together to solve a much larger problem than any of them would be capable of individually. Architecting is "divide and conquer" followed by "now mind your own business" followed by "so how do these things work together?" That is, each part can be built fairly independently of the other parts; in the end, however, these parts must be put together to solve the larger problem. A single system is almost inevitably partitioned simultaneously in a number of different ways: different sets of parts and different relations among the parts.
Architecture is what makes the sets of parts work together as a successful whole. Architecture documentation is what tells developers how to make it so.
For nearly all systems, quality attributes or engineering goalssuch as performance, reliability, security, or modifiabilityare every bit as important as making sure that the software computes the correct answer. Architecture is where these engineering goals are met. Architecture documentation communicates the achievement of those goals.
- Be concerned with the decomposition of the work into cooperating processes
- Manage the interprocess communication volume and data access frequencies
- Be able to estimate expected latencies and throughputs
- Identify potential performance bottlenecks
- Understand the ramifications of a network or processor fault
- Legislate usage relationships and communication restrictions among the parts
- Pinpoint parts of the system that are vulnerable to external intrusions
- Possibly introduce special, trusted components
All these engineering goals and their solutions are purely architectural in nature. Given these uses of architecture, a fundamental question emerges: How do you document an architecture so that others can successfully use it, maintain it, and build a system from it? This book exists to answer that question.
COMING TO TERMS
If we are to agree on what it means to document a software architecture, we should establish a common basis for what it is we're documenting. Although the term software architecture has multiple definitions, no universal definition exists. The Software Engineering Institute's Web site collects definitions from the literature and from practitioners; so far, more than 90 definitions have been collected. Following are a few of the most-cited definitions from published literature.
These and other similar definitions take a largely structural perspective on software architecture. They hold that software architecture is composed of elements, connections among them, and, usually, some other aspect or aspects, such as configuration or style, constraints or semantics, analyses or properties, or rationale, requirements, or stakeholders' needs. Mary Shaw has observed that there seem to be three additional main perspectives on architecture beyond the structural:
These perspectives do not preclude one another; nor do they represent a fundamental conflict about what software architecture is. Instead, they represent a spectrum in the software architecture community about the emphasis that should be placed on architecture: its constituent parts, the whole entity, the way it behaves once built, or the building of it. Taken together, they form a consensus view of software architecture and help us make sense of the concept.
What's the Difference Between Architecture and Design?
The question of how architecture is different from design has nipped at the heels of the architecture community for years.
Fortunately, the answer is easy. Architecture is design, but not all design is architecture. That is, many design decisions are left unbound by the architecture and are happily left to the discretion and good judgment of downstream designers and implementers. The architecture establishes constraints on downstream activities, and those activities must produce artifactsfiner-grained designs and codethat are compliant with the architecture, but architecture does not define an implementation.
You may ask, "What decisions are nonarchitectural? That is, what decisions does the architecture leave unbound and at the discretion of others?" To answer this question, we return to our definition of software architecture, cited in the preface: ". . . the structure or structures of the system, each of which comprises elements, the externally visible properties of those elements, and the relationships among them."
Thus, if a property of an architectural element is not visible, or discernible, to any other architectural element, that element is not architectural. The selection of a data structure, along with the algorithms to manage and access that data structure, is a typical example. Suppose that the architectural prescription for the data structure is that it provides programs, invoked from other architectural elements, that store and retrieve data; whether we choose a linked list, an array, a stack, or any other solution is therefore immaterial to those other elements, as long as our choice lets us meet the developmental, behavioral, and quality requirements levied on us.
"But wait," you protest. "You used the term architectural element: What's that? Are there nonarchitectural elements? If so, what's the difference?"
There may be nonarchitectural elements; their existence is unknown except to those who are outside an architectural context. For instance, a module may correspond to a work assignment for a development team; a module created under the doctrine of information hiding encapsulates a changeable aspect about the system. Modules are hierarchical entities; that is, a complex module, such as a work assignment, can be decomposed into smaller modules: smaller work assignments. Each module has an interface and an implementation. The interface to the parent is a subset of the union of the interfaces of the children.
Suppose that you're in charge of implementing module M and that, as far as the architect has stipulated, M has no submodules. Perhaps you discover that M's interface routines could all be implemented quite straightforwardly if you also designed and implemented a common set of services that they could all use. You assign a small subteam to design and implement thisthisthis what? Well, it's a work assignment, and it encapsulates a changeable secretnamely, the algorithms and data structures used by the common servicesso that makes it a module, a submodule of M. Let's call it M2:
"I get it," you say. "Because its existence is not known outside of M, M2 is not an architectural module."
It's tempting to agree at this point and be done with this, but that's not quite the right way to look at things. In some layered architectures, the layers at the top are not allowed to use the layers at the bottom; in essence, the bottom layers' services are not known to the top layers. But we would never say that the bottom layers of an architecture are nonarchitectural. The argument about "unknown outside of" appeals to a relation different from the one present in a module structure. Modules are related to one another by the contains relation, or shares a secret with relation. Whether a module's services are known or unknown by another module is a property of the uses relation, which is a different kind of animal.
"OK," you say. "So is module M2 an architectural element or not?"
I would say not, but not because it's "invisible" to the other modules outside its parent. I'm afraid you're not going to like the reason. It's a nonarchitectural element because the architect said sothat is, he or she didn't make it part of the architecture.
"You're joking," you say. "That's a completely arbitrary definition!"
Not really. The reason the architect didn't make it part of the architecture is that its existence or nonexistence was not material to the overall goals of the architecture. The architect gave you the freedom to structure your teamimplementing Mas you saw fit.
The fact is, no scale or scope or measure or line divides what is architectural and what is not. One person's architecture may be another person's implementation and vice versa. Suppose that M2 turns out to be very complicated and that the subteam you assign to it begins by giving M2 an internal structure. To the coders of M2, that structure is an architecture. But to the architecture of the system that includes M, the very existence of M2, let alone its internal structure, is an implementation detail.
Modules and other hierarchical elements are subject to confusion about where to draw the line between architecture and nonarchitectural design. If you want to be tediously precise about the matter, the coding of each subroutineor even the coding of a single line of codecould be considered a separate work assignment. Of course, we would not want to consider such minutiae to be architectural: The whole point of architecture is to let us reason about larger issues. So when should an architect stop decomposing modules into smaller and smaller work assignments? One heuristic comes from David Parnas [Parnas, 86, p. 363]. He says that a module is "small enough" when, in the face of a change, it would be just as easy to recode it as it would be to alter it. Technically speaking, you can't know a module's code size at design time, but if you can't make a good guess, you're probably not the right person to be the architect for the system you're working on.
Processes and other nonhierarchical elements can also be nonarchitectural. Suppose that the architect gave you a budget and the freedom to create up to 12 tasks and that these tasks do not synchronize or interact with any other tasks outside your work assignment. In that case, we could make the same argument: that these tasks, or elements, are nonarchitectural.
"All right," you sigh. "Once more, with clarity?"
Sure. Architecture is design, but not all design is architectural. The architect draws the boundary between architectural and nonarchitectural design by making those decisions that need to be bound in order for the system to meet its development, behavioral, and quality goals. (Decreeing what the modules are achieves modifiability, for example.) All other decisions can be left to downstream designers and implementers. Decisions are architectural or not, according to context. If structure is important to achieve your system's goals, that structure is architectural. But designers of elements, or subsystems, that you assign may have to introduce structure of their own to meet their goals, in which case such structures are architectural: to them but not to you.
Architecture is truly in the eye of the beholder. And what does all this have to do with documentation? If your goals are met by an architecture, document it as such, but expect the possibility that subsequent, finer-grained design may produce architectural documentationabout a small piece of your systemon its own.
 By "hierarchical element," we mean any kind of element that can consist of like-kind elements. A module is a hierarchical element because modules consist of submodules, which are themselves modules. A task or a process is not a hierarchical element.
COMING TO TERMS
Documentation, Description, Representation, Specification
What shall we call the activity of writing down a software architecture for the benefit of others or for our own benefit at a later time? Leading contenders are documentation, representation, description, and specification. For the most part, we use documentation throughout this book, and we want to explain our reasoning.
Specification tends to connote an architecture rendered in a formal language. Now, we are all for formal specs. (We have to be. One of usIverscounts himself as a formalist, and he intimidates the rest of us. In an early draft one of us called data flow diagrams a formal notation, and he just about gave himself an aneurysm. We recanted.) But formal specs are not always practical; nor are they always necessary. Sometimes, they aren't even useful: How, for example, do you capture in a formal language the rationale behind your architectural decisions?
Representation connotes a model, an abstraction, a rendition of a thing that is separate or different from the thing itself. Is architecture something more than what someone writes down about it? Arguably yes, but it's certainly pretty intangible, in any case. We felt that raising the issue of a model versus the thing being modeled would only raise needlessly diverting questions best left to those whose hobby, or calling, is philosophy: Does an abstraction of a tree falling in a model of a forest make a representation of a sound? Don't ask me; I haven't a clue. (Better yet, ask Ivers.)
Description has been staked out by the architecture description language (ADL) community. It's mildly curious that the formalists snagged the least rigorous-sounding term of the bunch. (If you don't believe this, the next time you board a jet ask yourself if you hope its flight control software has been specified to the implementers, or merely described.) One would think that the ADL purveyors' ambitions for their languages are not very great, but that is not the case. In any event, we did not want anyone to think that writing down an architecture is tantamount to choosing and using an ADL, so we eschewed description.
That leaves documentation. Documentation connotes the creation of an artifact: namely, a document, which may, of course, be electronic files, Web pages, or paper. Thus, documenting a software architecture becomes a concrete task: producing a software architecture document. Viewing the activity as creating a tangible product has advantages. We can describe good architecture documents and bad ones. We can use completeness criteria to judge how much work is left in producing this artifact and determining when the task is done. Planning or tracking a project's progress around the creation of artifacts, or documents, is an excellent way to manage. Making the architecture information available to its consumers and keeping it up-to-date reduces to a solved problem of configuration control. Documentation can be formal or not, as appropriate, and may contain models or not, as appropriate. Documents may describe, or they may specify. Hence, the term is appropriately general.
Finally, documentation is a longstanding software engineering tradition. Documentation is the task that you are supposed to do because it's good for you. It's what your software engineering teachers taught you to do, your customers contracted you to do, your managers nagged you to do, and what you always found a way not to do. So if documentation brings up too many pangs of professional guilt, use any term you like that's more palatable. The essence of the activity is writing downand keeping currentthe results of architectural decisions so that the stakeholders of the architecturepeople who need to know what it is to do their jobhave the information they need in an accessible, nonambiguous form.