This article is provided courtesy of IEEE Software Magazine.
Every interesting software-intensive system has an architecture. While some of these architectures are intentional, most appear to be accidental.
Since accidental is an emotionally explosive word, let's tease apart the elements of my statement. First, the terms interesting and software-intensive. For my purposes, an interesting system is one that has significant economic value; a software-intensive system is one that involves some degree of software/hardware interplay, such as that found not only in large distributed systems but also in smaller embedded systems or even captive uniprocessor or multicore systems. Second, the term architecture itself. Here, I'm not so much concerned about the definition (the terminology in IEEE Standard 1471 is quite sufficient for my needs) but rather the naming of particular architectural patterns. I'll say more about this later, but the fact that we cannot yet meaningfully enumerate a comprehensive set of architectural patterns or styles across domains is a gap in our understanding of software architecture. (Filling that gap is one desired outcome of my Handbook project.) Finally, the terms intentional and accidental. An intentional architecture is explicitly identified and then implemented; an accidental architecture emerges from the multitude of individual design decisions that occur during development, only after which can we name that architecture.
Philippe Kruchten has observed that "the life of a software architect is a long and rapid succession of suboptimal design decisions taken partly in the dark." The journey between vision and ultimate executable system is complex. For every interesting software-intensive system, that path is marked by myriad decisions, some large and some small, some of which advance progress while others represent vestigial dead ends or trigger points for scrap and rework. As Philippe also observes, the architecture of classical systems comes primarily from theft, whereas the architecture of unprecedented systems comes largely from intuition carried out in the context of a controlled exploratory process. The fact that this is so for software-intensive systems shouldn't come as a surprise, for as Henry Petroski explains in his book To Engineer Is Human (Vintage, 1992), all sound engineering disciplines advance by building on past successes while simultaneously mitigating causes of observable failure.
Thus, having an accidental architecture is not necessarily a bad thing, as long as
- the decisions that make up that architecture are made manifest and
- the essential ones are made visible as soon as they are instituted and then are allowed to remain visible throughout the meaningful life of that system.
Insofar as we can then name these architectures after they're formed, we can use these names and their associated semantics to communicate decisions using a common language, just as we can do now with design patterns, and perhaps even reuse these architectural patterns in future systems. In other words, by naming these accidental architectures, we again raise the level of abstraction by which we can describe and reason about a system.
In her book The Grammar of Architecture (Bulfinch, 2002), Emily Cole enumerates a set of 18 distinct architectural styles in civil engineering, ranging from Babylonian to Grecian and Islamic to Baroque, then on to Neoclassical and Picturesque. Her set isn't exactly complete or of suitable granularity—one could argue that Victorian, Craftsman, or even Gehrian are equally valid styles—but the fact that such things are even nameable reflects that field's maturity.
Gehrian? Well, therein lies a conundrum. The contemporary architect Frank Gehry, just like Daniel Libeskind, I.M. Pei, and many others, has a uniquely identifiable style that we don't quite know how to classify and thus name. Indeed, if you consider all the styles from Cole's book, you'll realize we can name them and distinguish one from another only because of the distance of time, having had the opportunity to reflect back on numerous instances of specific architectures and harvest their reoccurring patterns. The problem of naming software architectural patterns, therefore, is that we don't have a similar luxury of time or of as many identifiable reoccurring instances from which to harvest.
As part of my software archeological digs, I collect of lot of metadata, including the history of the system under study. In every case (taking into account that my work is self-selecting, for I'm only studying successful systems), I've uncovered a steady growth of architectural maturity within each domain. This maturity is represented by what evolutionists would call a punctuated rhythm consisting of architectural discovery, architectural stability, architectural collapse, and then a repeated cycle initiated by a harvesting of architectural patterns that survived the collapse. In other words, accidental architectures emerge but then become intentional only after they've proven themselves through time.