Software Engineering Institute Carnegie Mellon

Software Architecture
Latest Updates

TECHNOLOGIES
Documentation
Evaluations
Life-Cycle Integration
Products and Services
Reconstruction
Quality Attribute Reasoning

TOOLS and METHODS
ArchE
ARID
ATAM
CBAM
Design/ADD
QAW
Views and Beyond

LEARNING
Architect's Bookshelf
Architect's Duties, Skills, etc.
Bibliography
Books
Curriculum and
Certificate Programs
Definitions
Essays
Glossary
Presentations, Podcasts,
and Movies
Publications
(by topic)
Publications
(by type & date)

COMMUNITY
Community Resources
Upcoming_Events

Software Product Lines
Predictable Assembly from
Certifiable Components
Product Line Systems Program

Origins of Software Architecture Study

Brooks: The conceptual structure
In programming, the term architecture was first used to mean a description of a computer system that applied equally to more than one actual system. In 1969, Fred Brooks and Ken Iverson called architecture the "conceptual structure of a computer...as seen by the programmer". A few years later, Brooks (crediting Gerald Blaauw for the term) defined architecture as "the complete and detailed specification of the user interface. For a computer, this is the programming manual. For a compiler, it is the language manual... For the entire system it is the union of the manuals the user must consult to do his entire job." A careful distinction was drawn between architecture and implementation. Quoting Blaauw, Brooks writes, "Where architecture tells what happens, implementation tells how it is made to happen." This distinction survives today, and in the era of object-oriented programming it thrives.

Although the term architecture is still used today in some communities to refer to the user view of a system, it isn't what is meant by software architecture, which refers to the structure of the system quite hidden from the user. However, the notion of architecture as a common description of a class of systems -- i.e., an abstraction, where all the instantiations are said to exhibit the architecture -- endures, and is at the heart of the concept.

Dijkstra and Parnas: Structure matters
The study of software architecture is in large part a study of software structure that began in 1968 when Edsger Dijkstra pointed out that it pays to be concerned with how software is partitioned and structured, as opposed to simply programming so as to produce a correct result. Dijkstra was writing about an operating system, and first put forth the notion of a layered structure, in which programs were grouped into layers, and programs in one layer could only communicate with programs in adjoining layers. Dijkstra pointed out the elegant conceptual integrity exhibited by such an organization, with the resulting gains in development and maintenance ease.

David Parnas pressed this line of observation with his contributions concerning information-hiding modules (1972), software structures (1974), and program families (1975).

A program family is a set of programs (not all of which necessarily have been or will ever be constructed) for which it is profitable or useful to consider as a group. This avoids ambiguous concepts such as "similar functionality" that sometimes arise when describing domains. For example, software engineering environments and video games are not usually considered to be in the same domain, although they might be considered members of the same program family in a discussion about tools that help build graphical user interfaces, which both happen to use.

A program family can be enumerated in principle by specifying the decision tree that was or would be traversed in order to arrive at each member of the family. The leaves of the tree represent fielded, executing systems. The concept supports the notion of deriving a new member of the family from an extant one. The procedure is to backtrack up the decision tree until a node (decision point) historically common to both is reached, and then to proceed downward along the new path to derive the desired member. The concept also supports the notion of deriving several members of the family from a common decision point, thus making clear how each set of members resemble and differ from each other.

The point of the decision tree representation is to make clear the advantage of late binding and of prudently ordering -- and recording -- one's design decisions. Early design decisions should be ones that will most likely remain constant across members of the program family that one may reasonably expect to produce. In the context of this discussion, an early design decision is the adoption of a particular architecture, as defined below. Late decisions (near the leaves) in a prudently-structured decision tree should represent trivially-changeable decisions, such as the values of compile-time or even load-time constants.

The significance of the program family concept to software architecture is that software architecture embodies those decisions at or near the top of Parnas' program family decision tree.

All of the work in the field of software architecture may be seen as evolving towards a paradigm of software development based on principles of architecture, and for exactly the same reasons given by Dijkstra and Parnas: Structure is important, and getting the structure right carries benefits.

Meanwhile, back in the real world, maturing domains
In tandem with these important academic treatments of program and system structure came a long series of practical experiences working with systems in several highly populated domains. Consider compilers. Throughout the 1970's and 1980's, compiler design evolved from a series of distinct efforts, each one innovative and unprecedented, into one with standard, codified pieces and interactions. Today, textbooks about how to build a compiler abound, and the domain has matured to the point where no one today would think for a moment of building a compiler from scratch, without re-using and exploiting the codified experience of the hundreds of prior examples.

What exactly is re-used and exploited? Those decisions that are common to all compilers. Compiler writers can talk meaningfully with each other about lexical scanners, parsers, syntax trees, attribute grammars, target code generators, optimizers, and call graphs without even though the languages being compiled may look nothing at all alike. So, for instance, two compilers may have completely different parsers; one may be meticulously hand-written, the other may be automatically generated by a tool such as YACC. One may work for LALR(1) grammars; the other may only accept finite state machine grammars. But what is common is that both compilers have a component called a parser, which performs a function in both that (when viewed under a simple abstraction) is exactly the same.

Many other domains now exist that, through practice and repetition and sharing among the many early members of the family, now exhibit common structure, interconnection strategies, allocation of functionality to components, component interfaces, and an overall justifying rationale. The study of software architecture can be viewed as an ex post facto effort to provide a structured storehouse for this type of reusable family-wide design information. Work in software architecture can be seen as attempting to codify the commonality among members of a program family, so that the high-level design decisions inherent in each member of a program family need not be re-invented, re-validated, and re-described.