6 Patterns, architecture and decoupled design
One of the most important recent ideas in software development is that of a design pattern. Design patterns are standard solutions to recurring problems, named to help people discuss them easily and to think about design. They have always been around in computing, so that terms such as 'linked list' or 'recursive descent' are readily understood by people in the field.
Software patterns have been described as reusable micro-architectures. Patterns are abstract, core solutions to problems that recur in different contexts but encounter the same 'forces' each time. The actual implementation of the solution varies with each application. Patterns are not, therefore, ready-made 'pluggable' solutions. They are most often represented in object-oriented development by commonly recurring arrangements of classes and the structural and dynamic connexions between them. Perhaps the best known and useful examples of patterns occur in application frameworks associated with graphical user interface building or other well-defined development problems. In fact, some of the motivation for the patterns movement came from the apprehension of already existing frameworks that led people to wonder how general the approach was. Nowadays it is more usual to deliver frameworks in the form of flexible class libraries for use by programmers in languages that support the class concept, often C++ and Java. Examples of frameworks range from class libraries that are delivered with programming environments through the NeXtStep Interface Builder to the many GUI and client-server development systems now on the market such as Delphi, Visual Studio, Visual Age or Visual Basic.
Patterns are most useful because they provide a language for designers to communicate in. Rather than having to explain a complex idea from scratch, the designer can just mention a pattern by name and everyone will know, at least roughly, what is meant. This is how designers in many other disciplines communicate their design ideas. In this sense they are an excellent vehicle for the collection and dissemination of the anecdotal and unquantifiable data that Borenstein (1991) argues need to be collected before we can see real advances in the processes of building software. As with software architecture there are two different views of patterns abroad, both of which have value. To examine these we will first look at the roots of the patterns concept which lie outside the domain of software development, in the domain of the built environment. Hardly surprising then that patterns are closely related to software architecture.
Patterns are associated with the radical architect of the built environment, Christopher Alexander. >From the outset of his career Alexander has been driven by the view that the vast majority of building stock created since the end of World War II (which constitutes the great majority of all construction works created by human beings in the history of the species) has been dehumanizing, of poor quality and lacking all sense of beauty and human feeling. In his earliest publication Alexander presented a powerful critique of modern design (Alexander, 1964) contrasting the failures of the professional self-conscious process of design with what he called the unselfconscious process by which peasants' farmhouses, Eskimos' igloos and the huts of the Mousgoum tribesmen of the Cameroon amongst others create their living spaces. In the latter '...the pattern of building operation, the pattern of the building's maintenance, the constraints of the surrounding conditions, and also the pattern of daily life, are fused in the form' (p. 31) yet there is no concept of 'design' or 'architecture', let alone separate designers and architects. Each man builds his own house.
Alexander argues that the unselfconscious process has a homeostatic (i.e. self-organizing) structure that produces well-fitting forms even in the face of change, but in the self-conscious process this homeostatic structure has been broken down, making poorly-fitting forms almost inevitable. Although, by definition, there are no explicitly articulated rules for building in the unselfconscious process, there is usually a great weight of unspoken, unwritten, implicit rules that are, nevertheless, rigidly maintained by culture and tradition. These traditions provide a bedrock of stability, but more than that, a viscosity or resistance to all but the most urgent changes - usually when a form 'fails' in some way. When such changes are required the very simplicity of life itself, and the immediacy of the feedback (since the builder and homeowner are one and the same) mean that the necessary adaptation can itself be made immediately, as a 'one-off'. Thus the unselfconscious process is characterized by fast reactions to single 'failures' combined with resistance to all other changes. This allows the process to make a series of minor, incremental adjustments instead of spasmodic global ones. Changes have local impact only, and over a long period of time, the system adjusts 'subsystem by subsystem'. Since the minor changes happen at a faster rate of change than does the culture, equilibrium is constantly and dynamically re-established after each disturbance.
In the self-conscious process tradition is weakened or becomes non-existent. The feedback loop is lengthened by the distance between the 'user' and the builder. Immediate reaction to failure is not possible because materials are not close to hand. Failures for all these reasons accumulate and require far more drastic action because they have to be dealt with in combination. All the factors that drive the construction process to equilibrium have disappeared in the self-conscious process. Equilibrium, if reached at all, is unsustainable, not least because the rate at which culture changes outpaces the rate at which adaptations can be made.
Alexander does not seek a return to primitive forms, but rather a new approach to a modern dilemma: self-conscious designers, and indeed the notion of design itself, have arisen as a result of the increased complexity of requirements and sophistication of materials. They now have control over the process to a degree that the unselfconscious craftsman never had. But the more control they get, the greater the cognitive burden and the greater the effort they spend in trying to deal with it, the more obscure becomes the causal structure of the problem which needs to be expressed for a well-fitting solution to be created. Increasingly, the very individuality of the designer is turning into its opposite: instead of being a solution, it is the main obstacle to a solution to the problem of restoring equilibrium between form and context.
In his 1964 work, Alexander produced a semi-algorithmic, mechanistic 'programme' based on functional decomposition (supported by a mathematical description in an appendix) to address the issues he identified. He has long since abandoned that prescription. It is the rather more informal drawings he used in the worked example that seem to have a more lasting significance. These became the basis, it seems, for the patterns in his later work.
Alexandrian 'theory' is currently expressed in an 11-volume-strong literary project that does not include his 1964 work. Eight of these volumes have been published so far (though, at best, three of them, referred to as the patterns trilogy, The Timeless Way of Building, A Pattern Language and The Oregon Experiment, are familiar to parts of the software patterns movement). The ninth volume in the series, The Nature of Order, is eagerly awaited as it promises to provide the fullest exposition yet of the underlying theory. A common theme of all the books is the rejection of abstract categories of architectural or design principles as being entirely arbitrary. Also rejected is the idea that it is even possible to successfully design 'very abstract forms at the big level' (Alexander, 1996, p.8). For Alexander architecture attains its highest expression, not at the level of gross structure, but actually in its finest detail, what he calls 'fine structure'. That is to say, the macroscopic clarity of design comes from a consistency; a geometric unity holds true at all levels of scale. It is not possible for a single mind to envision this recursive structure at all levels in advance of building it. It is in this context that his patterns for the built environment must be understood.
Alexander et al. (1977) present an archetypal pattern language for construction. The language is an interconnected network of 253 patterns that encapsulate design best practice at a variety of levels of scale, from the siting of alcoves to the construction of towns and cities. The language is designed to be used collaboratively by all the stakeholders in a development, not just developers. This is premised, in part at least, by the idea that the real experts in buildings are those that live and work in them rather than those that have formally studied architecture or structural engineering. The patterns are applied sequentially to the construction itself. Each state change caused by the application of a pattern creates a new context to which the next pattern can be applied. The overall development is an emergent property of the application of the pattern language. The language therefore has a generative character: it generates solutions piece-meal from the successive addressing of each individual problem that each of the patterns addresses separately.
waist-high shelf (number 201 in the language) is an example pattern. It proposes the building of waist-high shelves around main rooms to hold the 'traffic' of objects that are handled most so that they are always immediately at hand. Clearly the specific form, depth, position and so on of these shelves will differ from house to house and workplace to workplace. The implementation of the pattern creates, therefore, a very specific context in which other patterns such as thickening the outer wall (number 211) can be used since Alexander suggests the shelves be built into the very structure of the building where appropriate, and things from your life (number 253) to populate the shelves.
The pattern which more than any other is the physical and procedural embodiment of Alexander's approach to design, however, is pattern number 208, gradual stiffening:
The fundamental philosophy behind the use of pattern languages is that buildings should be uniquely adapted to individual needs and sites; and that the plans of buildings should be rather loose and fluid, in order to accommodate these subtleties....
Recognize that you are not assembling a building from components like an erector set, but that you are instead weaving a structure which starts out globally complete, but flimsy; then gradually making it stiffer but still rather flimsy; and only finally making it completely stiff and strong. (Alexander et al., 1977, pp. 963-9.)
In the description of this pattern Alexander invites the reader to visualize a 50-year-old master carpenter at work. He keeps working, apparently without stopping, until he eventually produces a quality product. The smoothness of his labour comes from the fact that he is making small, sequential, incremental steps such that he can always eliminate a mistake or correct an imperfection with the next step. He compares this with the novice who with a 'panic-stricken attention to detail' tries to work out everything in advance, fearful of making an unrecoverable error. Alexander's point is that most modern architecture has the character of the novice's work, not the master craftsman's. Successful construction processes, producing well-fitting forms, come from the postponement of detail design decisions until the building process itself so that the details are fitted into the overall, evolving structure.
Alexander's ideas seem to have been first introduced into the object-oriented community by Kent Beck and Ward Cunningham. In a 1993 article in Smalltalk Report Beck claimed to have been using patterns for six years already, but the software patterns movement seems to have been kicked off by a workshop on the production of a software architect's handbook organized by Bruce Anderson for OOPSLA'91. Here met for the first time Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides - a group destined to gain notoriety as the Gang of Four (GoF). Gamma was already near to completion of his PhD thesis on 'design patterns' in the ET++ framework (Gamma, 1992). He had already been joined by Helm in the production of an independent catalogue. By the time of a follow-up meeting at OOPSLA in 1992, first Vlissides and then Johnson had joined the effort and, sometime in 1993, the group agreed to write a book that has been a best-seller ever since its publication in 1995. In fact, outside the patterns movement itself, many in the software development industry identify software patterns completely and totally with the GoF book.
However, the 1991 OOPSLA workshop was only the first in a series of meetings that culminated first in the formation of the non-profit Hillside Group (apparently so-called because they went off to a hillside one weekend to try out Alexander's building patterns) and then the first Pattern Languages of Programming (PLoP) conference in 1994. PLoP conferences, organized and funded by the Hillside Group, take place annually in America, Germany and Australia and collections of the patterns that are produced are published in a series by Addison-Wesley - four volumes to date. In addition the Hillside Group maintains a web site and numerous pattern mailing lists (Hillside Group, 2000). These communication channels form the backbone of a large and growing community that is rightly called the patterns movement.
A characteristic of the way patterns are developed for publication in the patterns movement is the so-called pattern writers' workshop. This is a form of peer-review which is loosely related to design reviews that are typical in software development processes, but more strongly related to poetry circles which are decidedly atypical. The special rules of the pattern writers' workshop (which are the modus operandi of the PLoP conferences) have been shown to be powerful in producing software patterns, written in easily accessible, regular forms known as pattern templates, at an appropriate level of abstraction. Rising (1998) reports on their effectiveness in producing a patterns' culture in the telecommunications company AGCS; and they are de rigeur in parts of IBM, Siemens and AT&T, all of which are known to have produced their own in-house software patterns, as well as publishing them in the public domain.
While the GoF book has won deserved recognition for raising the profile of patterns, for many it has been a double-edged sword. The GoF patterns form a catalogue of standalone patterns all at a similar level of abstraction. Such a catalogue can never have the generative quality that Alexander's pattern language claims for itself and, to be fair, the Gang of Four freely admit that this was not the aim of their work.
The GoF book includes 23 useful design patterns, including the following particularly interesting and useful ones:
Some cynics claim that some of the GoF patterns are really only useful for fixing deficiencies in the C++ language. Examples of these might arguably include Decorator and Iterator. However, this very suggestion raises the issue of language-dependent vs. language-independent patterns. Buschmann et al. (1996) (also known as the Party of Five or PoV) from Siemens in Germany suggest a system of patterns that can be divided into architectural patterns, design patterns and language idioms. They present examples of the first two categories. Architectural patterns include: Pipes and Filters, Blackboard systems, and the Model View Controller (MVC) pattern for user interface development. Typical PoV design patterns are called:
The reader is advised by the PoV to refer to all the GoF patterns as well. The PoV book can therefore be regarded as an expansion of the original catalogue, not merely through the addition of extra patterns, but by addressing different levels of abstraction too. The whole-part pattern is exactly the implementation of the composition structures that form part of basic object modelling semantics. In that sense it appears to be a trivial pattern. However, since most languages do not support the construct, it can be useful to see the standard way to implement it. It is a rare example of an analysis pattern that maps directly to an idiom in several languages: a multi-language idiom. The best known source of idiomatic (i.e. language-specific) patterns is Jim Coplien's book on advanced C++ which predates the GoF book by some three years (Coplien, 1992). C++ 'patterns' (the book does not use the term) that Coplien presents include:
Whilst experienced object-oriented programmers will feel immediately familiar with many of these patterns, almost everyone will recognize the ideas behind caches and recursive composites. These too can be regarded as design and/or analysis patterns. Cache should be used when complex computations make it better to store the results rather than recalculate often; or when the cost of bringing data across a network makes it more efficient to store them locally. Clearly this is a pattern having much to do with performance optimization. It is also worth noting that patterns may use each other; this pattern may make use of the observer pattern (see below) when it is necessary to know that the results need to be recalculated or the data refreshed. This can be done eagerly or lazily, depending on the relative read and update profiles.
Although it is often good practice - unless dealing with derived dependencies - to document structures such as inheritance and aggregation separately, as we saw earlier, documenting patterns often requires that they are expressed in terms of more than one structure. Recursive, extensible structures such as binary trees and lists are a good example: a list is recursively composed of an atomic head and a tail which is itself a list, and a program is made up of primitive statements and blocks that are themselves made of blocks and statements. We can use a Catalysis framework template to document a general case as in Figure 38, in which one might substitute Block for <Node>, Program for <Branch> and Statement for <Leaf>.
Figure 38 Recursive composites.
We process recursive structures by recursive descent and need to specify - in the template - whether looping is prevented by including constraints. In OCL such a constraint can be written:
context Node::ancestors = parent + parent.ancestors AND
context Node:: not(ancestors includes self)
Strictly speaking, addition is not defined over sets in OCL. The plus sign is an abbreviation introduced in Catalysis, with the advantage of symmetry. The correct OCL form is: Set1 -> union(Set2).
The list and the block patterns can be regarded as whole objects or wrappers and the pattern merely describes their internal structure.
The above examples indicate that a standard pattern layout may be beneficial, and many proponents adopt a standard based on Alexander's work: the so-called Alexandrian form. This divides pattern descriptions into prose sections with suitable pictorial illustrations as follows - although the actual headings vary from author to author.
Kent Beck has produced a book of 92 Smalltalk idioms (Beck, 1997) and there have been a number of language-specific 'versions' of the GoF book, notably for Smalltalk (Alpert et al., 1998) and Java (Grand, 1998; Cooper, 2000). Although many of the PoV architectural patterns exist also among the SEI's 'styles', it is crucial to note their different purposes. Both are abstracted from software development best practice, but by the SEI in order to collect and formalize (and presumably later automate) them, by the PoV in order to further generalize that practice.
The overwhelming majority of software patterns produced to date have been design patterns at various levels of abstraction but Fowler (1997) introduces the idea of analysis patterns as opposed to design patterns. Fowler's patterns are reusable fragments of object-oriented specification models made generic enough to be applicable across a number of specific application domains. They therefore have something of the flavour of the GoF pattern catalogue (described in that book's subtitle as 'elements of reusable object-oriented software') but are even further removed from Alexander's generative concepts. Examples of Fowler's patterns include:
There are many more, some specialized into domains such as Health or Accounting.
The problem with these patterns is that even the simplest ones - like Accountability - are really quite hard to understand compared to the difficulty of the underlying problem that they solve. One of us had three goes at reading the text before really understanding what was going on. At the end of this process he found that he knew the proposed solution already but would never have expressed it in the same terms.
Maiden et al. (1998) propose a pattern language for socio-technical system design to inform requirements validation thereof, based on their CREWS-SAVRE prototype. They specify three patterns as follows:
The value of these patterns may be doubted because, like Fowler's analysis patterns, they seem to state the obvious; and they fail to address the sort of task or system usage patterns represented by our task association sets or use case refinement. Also, it could be argued that they are nothing but design principles; just as completion provides a well-known design principle in HCI. On the other hand, their operationalization in the CREWS-SAVRE system indicates that they may have a specialized practical value in this and certain other contexts.
There has also been interest in developing patterns for organizational development (Coplien, 1995; O'Callaghan, 1997, 1997a, 1998). Coplien applies the idea of patterns to the software development process itself and observes several noteworthy regularities. These observations arose out of a research project sponsored by AT&T investigating the value of QA process standards such as ISO9001 and the SEI's Capability Maturity Model. Working from a base concept that real processes were characterized by their communication pathways, Coplien, together with Brad Cain and Neil Harrison, analysed more than 50 projects by medium-size, high productivity software development organizations, including the Borland team charged with developing the Quattro Pro spreadsheet product. The technique they used was to adapt CRC cards and to get, in a workshop situation, representatives of the development organization under focus to enumerate rôles (as opposed to job descriptions), identify and categorize the strength of the relationships between those rôles (as either Weak, Medium and Strong) and then to rôle-play the development process in order to validate their judgements. The information was then input into a Smalltalk-based system called Pasteur that produces a variety of different sociometric diagrams and measures. From these, Coplien et al. were able to identify the commonly recurring key characteristics of the most productive organizations and develop a 42-strong pattern language to aid the design of development organizations. Included in the language are patterns such as these:
A typical application of such organizational patterns is the combined use of gatekeeper and firewall in, say, a situation where a pilot project is assessing new technology. The software development industry excels at rumour-mongering, a situation fuelled by the practice of vendors who make vapourware announcements long in advance of any commercial-strength implementations. Over-attention to the whispers on the industry grapevine, let alone authoritative-looking statements in the trade press, can seriously undermine a pilot project. Developers lose confidence in Java, say, because of its reputation for poor performance or a claimed lack of available tools. Yet, at the same time, some news is important: for example, the publication of Platform 2 for Java. A solution is to build official firewalls and then create a gatekeeper rôle where a nominated individual, or perhaps a virtual centre such as an Object Centre, is responsible for filtering and forwarding the useful and usable information as opposed to unsubstantiated scare stories, junk mail and even the attention of vendors' sales forces.
More interesting than the individual patterns themselves, however, is the underlying approach of Coplien's language which is much closer to the spirit of Alexander's work than anything to be found in the GoF or PoV books, for example. First, since its very scope is intercommunication between people, it is human-centred. Second, it is explicitly generative in its aim. Coplien argues that while software developers do not inhabit code in the way that people inhabit houses and offices, as professionals they are expert users of professional processes and organizations. Therefore, just as Alexander's language is designed to involve all the stakeholders of building projects (and, above all, the expertise of the users of the buildings) so process designers have to base themselves on the expertise of the victims of formal processes - the developers themselves. Coplien's attempt to create an avowedly Alexandrian pattern language seems to push the focus of his patterns away from descriptions of fragments of structure (as is typical in the GoF patterns) much more towards descriptions of the work that has to be done. In going beyond mere structure Coplien's patterns have much more of a feel of genuine architecture about them than do many other pattern types available.
In fact, it is clear that from common roots there are two polarized views of patterns abroad today. One view focuses on patterns as generic structural descriptions. They have been described, in UML books especially, as 'parameterized collaborations'. The suggestion is that you can take, say, the structural descriptions of the rôles that different classes can play in a pattern and then, simply by changing the class names and providing detailed algorithmic implementations, plug them into a software development. Patterns thus become reduced to abstract descriptions of potentially pluggable components. A problem with this simplistic view occurs when a single class is required to play many rôles simultaneously in different patterns. Erich Gamma has recently re-implemented the HotDraw framework, for example, in Java. One class, Figure, appears to collaborate in fourteen different overlapping patterns - it is difficult to see how the design could have been successful if each of these patterns had been instantiated as a separate component. More importantly, this view has nothing to say about how software projects should be put together, only what (fragments of) it might look like structurally. The other view regards them simply as design decisions (taken in a particular context, in response to a problem recognized as a recurring one). This view inevitably tends toward the development of patterns as elements in a generative pattern language.
Support for this comes from the work of Alan O'Callaghan and his colleagues in the Object Engineering and Migration group and Software Technology Research Laboratory at De Montfort University. O'Callaghan is the lead author of the ADAPTOR pattern language for migrating legacy systems to object and component-based structures. ADAPTOR was based initially on five projects, starting in 1993, in separate business areas and stands for Architecture-Driven And Patterns-based Techniques for Object Re-engineering. It currently encapsulates experiences of eight major industrial projects in four different sectors: telecommunications, the retail industry, defence and oil exploration. O'Callaghan argues that migrating to object technology is more than mere reverse engineering, because reverse engineering is usually (a) formal and (b) focused purely on the functional nature of the legacy systems in question and (c) assumes a self-similar architecture to the original one. The most crucial information, about the original design rationales, has already been lost irretrievably. It cannot be retrieved from the code because the code never contained that information (unless, of course, it was written in an unusually expressive way). The best that traditional archaeological approaches to reverse engineering can achieve is to recreate the old system in an object-oriented 'style' which, more often than not, delivers none of the required benefits.
The approach, pioneered by Graham (1995) and O'Callaghan, was to develop object models of the required 'new' system and the legacy system and, by focusing on the maintainers and developers (including their organizational structure) rather than the code or design documentation, determine only subsequently what software assets might already exist that could be redeployed. O'Callaghan's group turned to patterns in the search for some way of documenting and communicating the common practices that were successful in each new project (legacy systems present especially wicked problems and are, overall, always unique unto themselves). At first, public domain, standalone design patterns were used but quickly his team were forced to mine their own. Then problems of code ownership (i.e. responsibility for part of a system being re-engineered belonging to someone other than the immediate client), caused by the fact that migrations typically involve radical changes at the level of the gross structure of a system, required that organizational and process problems be addressed also through patterns. Finally, observations that the most powerful patterns in different domains were interconnected suggested the possibility of a generative pattern language.
ADAPTOR was announced in 1998 as a 'candidate, open, generative pattern language'. It is a candidate language for two reasons: first, despite the overwhelming success of the projects from which it is drawn ADAPTOR is not comprehensive enough in its coverage or recursed to a sufficient level of detail to be, as yet, truly generative. Secondly, O'Callaghan has different level of confidence in the different patterns with only those having gone through the patterns workshops of the patterns movement being regarded as fully mature. Patterns yet to prove themselves in this way are regarded as candidate patterns. ADAPTOR is open in a number of senses too. First, like any true language, both the language itself and the elements that comprise it are evolvable. Many of the most mature patterns, such as get the model from the people, which was first presented in 1996 at a TelePlop workshop, have gone through numbers of iterations of change. Secondly, following Alexander et al. (1977), O'Callaghan insists that patterns are open abstractions themselves. Since no true pattern provides a complete solution and every time it is applied it delivers different results (because of different specific contexts to which it is applied), it resists the kind of formalization that closed abstractions such as rules can be subject to. Finally, and uniquely amongst published software pattern languages, ADAPTOR is open because it makes explicit use of other public-domain pattern languages and catalogues, such as Coplien's generative development-process language already cited, or the GoF and PoV catalogues.
Patterns in ADAPTOR include the following.
Something of the open and generative character aspired to by ADAPTOR can be gained from looking at the typical application of patterns to the early phases of a legacy system migration project. Underpinning ADAPTOR is the model-driven approach described earlier. O'Callaghan's problem space models comprise object types and the relationships between them, which capture the behaviour of key abstractions of the context of the system as well as the system itself. Archetype is therefore one of the first patterns used, along with get the model from the people and pay attention to the folklore. At an early stage strategic 'what-if' scenarios are run against this model using buffer the system with scenarios. Shamrock is applied in order to decouple the concept domain object types from the purely system resources needed to deliver them at run time. The concept domain 'leaf' can then be factored into packages using time-ordered coupling to keep types with similar change rates (discovered through the scenario-buffering) together. Coplien's Conway's Law is now utilized to design a development organization that is aligned with the evolving structure of the system. Code ownership (another Coplien pattern) makes sure that every package has someone assigned to it with responsibility for it. An ADAPTOR pattern called trackable component ensures that these 'code owners' are responsible for publishing the interfaces of their packages that others need to develop to, so that they can evolve in a controlled way. The GoF pattern façade is deployed to create a scaffolding for the detailed structure of the system. It is at this point that decisions can be made as to which pieces of functionality require new code and which can make use of legacy code. The scaffolding ensures that these decisions, and their implementation consequences, can be dealt with at a rate completely under the control and at the discretion of the development team without fear of runaway ripple effects. For the latter, semantic wrappers are used to interface the old legacy stuff to the new object-oriented bits.
Even with this cursory example we can see how the language addresses all of the important issues of architecture (client's needs, conceptual integrity, structure, process and organization, etc.) as well as getting quickly to the heart of the issues of legacy migration. O'Callaghan reports that, when outlining this approach at a public tutorial, one member of the audience objected that the model-driven approach was not re-engineering at all but just 'forward engineering with the reuse of some legacy code'. In reply, O'Callaghan agreed and stated that that was just the point. On further consideration, he decided that many of ADAPTOR's patterns were not specific to legacy migration at all. As a result ADAPTOR is currently being regarded as a subset of a more general language on architectural praxis for software development in a project codenamed the Janus project (O'Callaghan, 2000b).
The debate about the nature of software patterns ('parametrized collaborations' versus 'design decisions'; pattern catalogues versus pattern languages) itself both reflects, and affects, the debates about software architecture. That relationship has been sharply exposed by Coplien's guest editorship of IEEE Software magazine in the Autumn of 1999. The issue was a special feature on software architecture in which Coplien published, amongst others, Alexander's keynote talk to the OOPSLA conference in San Jose, California in 1996 (Alexander, 1999). In his editorial, re-evaluating the architectural metaphor, Coplien identified two fundamental approaches to software development: the 'blueprint' or 'masterplan' approach versus that of 'piecemeal growth' (Coplien, 1999). Coplien suggests that the immature discipline of software architecture is suffering from 'formal envy' and has borrowed inappropriate lessons from both the worlds of hardware engineering and the built environment. Symptoms of its crisis are the separation of the deliverables of architecture from the artefacts delivered to the customer and the reification of architecture as a separate process in a waterfall approach to software development. Following the architect of the built environment Ludwig Miles van der Rohe, Coplien proclaims, as does Alexander as we have seen, that 'God lives in the details' and that clarity at the macro level can only be judged by whether it incorporates the fine details successfully. He further asserts: 'The object experience highlights what had been important all along: architecture is not so much about software, but about the people who write the software' (p. 41).
The main point about coupling and cohesion is that it permits people to work socially to produce a piece of software and both recognize and value their own particular contribution. Coplien points to CRC cards and their use in object-oriented development as the classic example of software design's anthropomorphic nature. >From this perspective, software patterns were the next wave in the advance of a software architectural practice of this kind. As Coplien quite rightly points out, the patterns movement has always celebrated the otherwise lowly programmer as the major source of architectural knowledge in software development. Beyond that it recognizes the deep character of the relationship between code's structure and the communication pathways between the people developing and maintaining it. In doing so, Coplien argues, patterns have taken software development beyond the naïve practice of the early days of objects, which fell short of its promise because it was still constrained by a purely modular view of software programs, inherited from the previous culture. Further advance requires liberation from the weight of 'the historic illusions of formalism and planning' (p. 42).
Richard Gabriel, who is currently a member of the Hillside Group, a master software practitioner as well as a practising poet, suggests that there are two reasons why all successful software development is in reality piecemeal growth. First, there is the cognitive complexity of dealing not only with current, but possible future, causes of change which make it impossible to completely visualize a constructible software program in advance to the necessary level of detail with any accuracy (Gabriel, 1996). Second, there is the fact that pre-planning alienates all but the planners. Coplien, Gabriel and the entire patterns movement are dedicated to developing practices that combat this social alienation. In doing so they impart a profound social and moral obligation to the notion of software architecture. In the face of these stark realities the only alternative to piecemeal growth is the one once offered by David Parnas: fake the blueprints by reverse engineering them once the code is complete.