Essays on Software Architecture
The following essays on software architecture have been provided by the software engineering community. If you have one that you would like to post, please send it in.
- Architecture Paradox - Dr. Subrahmanyam Allamaraju
- Hunting the Product Line Architecture - Joe Batman, Software Engineering Institute
- Characteristics of an Organization with Mature Architecture Practices - Joe Batman, Software Engineering Institute
- James Madison and the Role of the Architect - Dana Bredemeyer (bio), Bredemeyer Consulting
- Origins of Software Architecture Study - Paul Clements (bio), Software Engineering Institute
- Whats the Difference Between Architecture and Design? - Paul Clements (bio), Software Engineering Institute
- Multi-Paradigm Design for C++ - James O. Coplien (bio)
- Architecture Team Organization - Soviet Style - David Emery (bio), DSCI Inc.
- Architecture by "20 Questions" - David Emery (bio), DSCI Inc.
- Strategic Architecting1 - Rick Kazman (bio), Software Engineering Institute
- Architecture and Design - John Klein (bio), Avaya, Inc.
- The Tao of the Software Architect - Lao-Tsu, revisited by Philippe Kruchten (bio), Rational Software, Canada
- What do software architects do? - Philippe Kruchten (bio), University of British Columbia, Canada
- Eight Architecture Lessons from History - Srikanth Narasimhan, Cisco Systems
- Things to Do in Denver When You're an Architect - Rob van Ommering (bio), Philips Research Laboratories
- Are you a Software Architect yet? - Sathyanarayana Panduranga, Hewlett Packard India
- Software Architecture for Product Families - M. Jazayeri (bio), A. Ran, and F. van der Linden (bio)
- Lesson Learned About Architecture: Unstructured and Eclectic - Clayton Sprung, Consulting Analyst BCTEL
- The Golden Age of Software Architecture: A Comprehensive Survey - Mary Shaw (bio), Carnegie Mellon University and Paul Clements (bio), Software Engineering Institute
1 This article is the latest entry to The Architect, a featured column on software architecture in news@sei.
We welcome short essays about software architecture. If you have one that you would like to post, send it in.
Hunting the Product Line Architecture
Joe Batman
Software Engineering Institute
Introduction
This technical note discusses some of the issues related to evaluating architectures and organizations within the context of product lines. The focus here is on one aspect of the product line: the architecture. The architecture is the basis on which the product line is built and, therefore, assumes a primary role in determining success when organizations attempt to create and sustain a product line. The bias here is on the use of a prescriptive architecture. This and other terms are discussed in the following section.
The discussion below is intended to provide guidance for evaluation in two areas. One set of guidelines is provided for evaluation of existing architectures to determine their efficacy for product lines. A second set of guidelines is discussed for evaluating development organizations to determine if they are sufficiently mature in their architecture-centric practices to create and maintain effective architectures for their product lines.
The indicators discussed are not intended to be exhaustive nor can one develop a simple quantitative measure by adding up some sort of score on points satisfied or missed. Creating architectures is a complex business and we are only starting to understand how to do this in a systematic way. Readers should view the guidelines as an aid to creating a comprehensive picture of a particular architecture's strengths and weakness and an organization's level of architecture-centric practice maturity.
Architecture Team Organization - Soviet Style
David Emery (bio)
DSCI
Inc.
Email: demery@dsci-usa.com
From my observation, one key characteristic of effective software architecture groups is they follow a "Soviet" organizational model. There must be broad representation by the stakeholder constituencies, but the actual work is done by a much smaller group. More importantly, the architecture itself is produced and led by the chief/lead architect, guiding a select group of advisors. So software architecture may be a group activity, but it is one that depends on the leadership skills of the architect, to develop comprehensive solutions and lead consensus-building around the chief architect's direction. The effective chief architect must be willing to impose his will on both his small group of advisors and on the larger constituencies, preferably through consensus-building, but by fiat and direction when necessary, overruling all of his advisors on occasion. His inner circle must be willing to debate issues, but when the decision is made, they must support the decision (or leave the project).
In other words, we have:
- Party Congress - Large group that ratifies decisions presented to them
- Poliburo - Representative group that actually debates and makes the decisions that the Congress ratifies
- Central Committee - Select small group that writes the decisions for the Politburo to debate
- General Chairman - Person who tells the Central Committee what to write
The bottom line is that effective architecture is not done by committee, but should look that way :-)
Whats the Difference Between Architecture and Design?
Paul Clements (bio)
Software Engineering Institute
(based on "Documenting
Software Architectures: Views and Beyond")
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 preferred definition of software architecture (from Software Architecture in Practice, 2nd edition): ...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: Whats that? Are there nonarchitectural elements? If so, whats 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 youre in charge of implementing module M and that, as far as the architect has stipulated, M has no submodules. Perhaps you discover that Ms 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, its 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. Lets call it M2.
I get it, you say. Because its existence is not known outside of M, M2 is not an architectural module.
Its tempting to agree at this point and be done with this, but thats 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 modules 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 its invisible to the other modules outside its parent. Im afraid youre not going to like the reason. Its a nonarchitectural element because the architect said sothat is, he or she didnt make it part of the architecture.
Youre joking, you say. Thats 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 persons architecture may be another persons 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.
Processes and similar 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 systems 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, which has implications about its 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.
Are you a Software Architect yet?
Contributed by Sathyanarayana Panduranga
Software Design
Engineer, Hewlett Packard India, Bangalore, India
Email:
sathyap@india.hp.com
Software architecture is the blueprint of a software system. It provides an overview of the composition and functionality of the given software system. Just like a structural architect, a software architect needs to analyze the requirements, determine components that should be used to build the system, and support the project by guiding and solving problems all along the execution cycle. Architecting software is like planning for war. Past experiences are very useful here. Strategizing gives you an edge. Understanding of the domain provides you with capability to analyze the requirements and envisioning a solution. Exposure to various tools and technologies imparts in you the ability to choose among the various solutions available, and anticipate and solve technical problems.
A person becomes a software architect when she has gained enough breadth and depth in the relevant domain and technologies, and has the capability to envision a software system before it is developed.
Architects are needed for most of the Software Projects, more as the navigator for a sailing ship. Architects design the software system, guide the development team in implementing the system, and anticipate/diagnose problems, find/develop solutions to those problems. These days, most of the organizations are realizing the importance of software architects, because with an architect you are no longer shooting in the dark.
Architects need to have good written/spoken communication since they have to convince the people above and bellow them in the hierarchies about their ideas effectively, strong development and debugging skills, cross domain and technology proficiency and appreciation, and customers point of view can be very useful for an architect.
Due to the maturity of Software Development practice, there are several predefined solutions available for certain problems called Patterns. Design and Architecture patterns are a vogue in the Software Development industry. They are the solutions for a recurring class of problems. Most of the time, they are the best possible solutions to those problems. Knowledge of patterns in her domain/technology areas is an added advantage for an architect.
For a person, who is excited by new tools, technologies and domains, who is on the lookout for challenging problems to solve, who is capable of thought leadership, who equates her success to that of the customers, the role of Software Architect is a natural progression.
Architecture Paradox
Dr. Subrahmanyam Allamaraju
Introduction
A 1996 technical report [1] from the Software Engineering Institute, in its introduction points out that software architecture is still a relatively immature area from both research and practice perspectives. The same holds true in 1999 after maturity and emergence of several generic as well as domain-specific architectures. Today, the area is largely immature not because of lack of research, but lack of its practice. But why is it difficult to practice software architecture?
In commercial software industry, where products and applications are required to be built over very short time-frames with tight budgets, the term "architecture," though widely used, is rarely practiced as a concept or as an integral part of software building. Ironically, it is this specific industry segment that requires more emphasis on software architecture for at least two reasons: budgetary constraints, and shorter time to deployment. Both these factors demand protection of investments in information technology. Protection of investments requires protection of software architecture against changing requirements. In a nutshell, this is the focus of this article.
While architecture is generally perceived to be crucial for any software development exercise, in practice, architectures are rarely part of software development life-cycles, when so, rarely complete, and when complete, rarely protected and adhered to. This is one of the reasons why changes to software are expensive. Despite this, architectures are sought by concerned parties in almost all software development projects.
The purpose of this article is to discuss "Architecture Paradox" and bring out the conflicting forces that influence the architecture over the life-time of software products and applications. This paper also presents some early ideas on how to build software systems that defy the architecture paradox. Note that this paper does not attempt to prescribe a process for building software architecture, but indicates the activities the architect must undertake in designing an architecture, and the rationale behind these.
What is Software Architecture?
This article does not attempt to define or redefine architecture as applicable to software. The focus of this article is, instead, on the purpose and role of architecture during the software life cycle and beyond, to identify the factors that affect the architecture, and to finally discuss how to address the conflict between these factors. Readers interested in what software architecture is, should refer to [1] and [2].
For the purpose of the present discussion, the following definition and explanation (both from [1]) are relevant.
Architecture: Structure of the components of a program/system, their interrelationships, and principles and guidelines governing their design and evolution over time.
Software architecture usually refers to some combination of structural views of a system, with each view a legitimate abstraction of the system with respect to certain criteria, that facilitates a particular type of planning or usage.
From the above, note the following.
- Software architecture represents the structure of the software. This includes the structural arrangements of software components, and various static and dynamic interrelationships between these components.
- Software architecture is expressed using certain views, each of which serves a specific purpose. Each view is a specific abstraction of the architecture, for a specific purpose.
- Software architecture includes the principles behind design and evolution of the software.
The following are some of the essential characteristics of architecture.
- Software architecture should represent a high-level view of the system revealing the structure, but hiding all implementation details. Specifically, it should reveal attributes such as responsibilities (of the constituents of the architecture), distribution, and deployment.
- Architecture should realize all the use case scenarios. While the use case model serves to record the functional requirements as seen by various actors, the architecture should enable the stake holders of the software to walk through the scenarios of each use case. This guarantees that the structure as represented by the architecture meets the functional requirements.
- It should present other systemic views to all the stake holders of the software. Examples are - a component view for the development team, a network-centric deployment view for the network and hardware team, and a distribution-centric deployment view for the installation team etc.
However, how does an architecture look like? Some of the common representations of software architecture are as follows. As discussed below, none of these representations are complete.
- High-level design: A simplistic approach is to represent the architecture as a concise view of a high-level design of the software. However, design is an implementor's view of the software - a view that reveals how to arrive at the structure of the software. So a high-level design does not necessarily represent the architecture of the software.
- Deployment: This is the most common form of representations of architecture. In this view, the software is described in terms of how it is deployed across various platforms, and how these parts communicate with each other. Note that deployment view is only one of the possible views of architecture, and does not necessarily reveal the structure of the software. Also note that during the life-cycle of a software, the deployment could change with no or minimal changes to the structure of the software. This is one of the reasons that is driving distributed component based technologies.
- Generic Technology Architectures: In this form, software architecture is represented as a two-tier, three-tier or a multi-tier system. Note that architectures such as these, distributed (and layered) architectures such as COM or CORBA, or component based architectures such as MTS or EJB are generic and do not address the needs of the domain in which the software is to operate and evolve. However, these technology architectures provide the basis for developing domain specific application architectures.
As described in [1] and [2], an architecture should at least present the following views of the software (in the order of the importance).
- Logical or Conceptual View: This view of the software represents various abstractions of the system and accounts for various use case scenarios. Using this view, one should be able to walk through these abstractions to realize the use case scenarios. In the case of distributed applications, some of these abstractions may directly map to distributed components.
- Deployment View: As pointed earlier, this view depicts how various parts of the software are deployed.
In both the views, it is necessary to depict responsibilities of each of the parts of the architecture, static and/or dynamic dependencies between them, the nature of communication between the parts, etc. Additional views such as development views (to show how the application will be developed) and process views (to reveal threading, concurrency etc.) may also be considered if required.
In general, software architecture is considered ([1], [2]) important as it serves as a means of mutual communication between the stake holders of the software, allows to capture early design decisions, and lets the architecture be reused for similar systems in the same domain.
However, these are only consequences of an architecture design. The fundamental requirement for software architecture is to design a structure for the software considering long-term consequences. As discussed by Bennett [3], software is considered to be inntrinsically complex because of the fine granularity of programming language constructs (objects, classes, methods etc). Bennet points out that this makes the structure "soft." It is during the architecture design phase, that an architect can "harden" the structure of the software, before implementing the architecture with "soft" language constructs. However, before approaching the architecture design problem, it is necessary to consider the conflicts that a typical software faces.
Architecture Paradox
To be successful, a software must face two challenges: survival and evolution. These two are conflicting challenges. A software survives as long as it serves the requirements for which it was built. However, in a user-world where requirements, operational constraints and technology continue to change, survivability, though necessary, is not sufficient. The software, in addition, should be evolutionary. A software evolves as long as it can be adopted to meet changing demands. However, in an attempt to evolve, the software can not afford to lose its survivability. Both these challenges tend to affect the architecture in opposing directions, leading to the "architecture paradox."
Figure 1: Architecture Paradox: Survival vs Evolution |
Note that, a software's ability to survive and evolve (without loss of the other) depends on its structure as represented by its architecture.
To explain this architecture paradox, consider a software that meets its current requirements. Such a system is characterized by an architecture that realizes all use case scenarios and meets other requirements (such as performance, scalability etc). As requirements and other influencing factors change, the software begins to lose its survivability, as it can not yet meet the changed conditions. To bring back survivability, the software should be evolved to meet the changes. However, as Brooks [4] points out, changes made to a software may increase its entropy. This manifests in increased complexity, as seen by one or more of the following:
- Increased number of interdependencies between the parts of the software.
- Violation of structure (layers, tiers etc.).
- Violation of design goals.
Despite the above, the software may still be able to meet its changed requirements. However, due to the increased entropy, further changes to the software trigger a positive feedback mechanism, and increase the entropy further. Ultimately, the architecture of the software breaks down and further changes become almost impossible. The software loses its survivability.
Thus, in an attempt to evolve, the software may lose its survivability as shown in Figure 1. This is the architecture paradox.
An architecture can last longer only if it can defy the architecture paradox. But how to design such an architecture? What is the role of the architect in doing so? The rest of this paper addresses these questions.
A Solution?
For any system to adopt to changing functions and evolve, its growth (i.e., changes) should be dictated by certain principles (or values). These principles are not generic, but are meant to meet certain goals. The system should represent and protect the principles that it is built for.
In the case of software, the principles dictate the design and development. The role of the architect is to identify the goals, devise the principles, and build the architecture according to these principles. These principles should be encapsulated in the architecture such that the architecture dictates certain design and development constraints while leaving scope for changes that follow the principles.
Accordingly, this paper suggests a three-stage approach to design architectures that defy the software paradox. These are - to identify the of goals of the architecture, to discover the principles based on the goals, and to design an architecture integrating these principles. The capability of the system to survive and evolve increases as the focus tends to reach the third stage.
The approach suggested in this paper is based on the presumptions that
- it is possible to anticipate changes to software, and
- it is possible to build software architectures and designs that are resilient to change.
The motivation behind these presumptions is based on the following:
- Most of the application domains are mature enough to predict changes.
- Even in cases where the domains are turbulent, certain technologies and design patters based on components, and reflection make architectures resilient.
For a discussion on change resilience patterns in software architecture and design, refer to [5].
The following sections discuss the three phases in detail.
Identify the Goals of Architecture
The fundamental goal of the architecture of a software is to realize all its use cases. It should facilitate all use case scenarios to be implemented in the software. However, this is just one of the contributing factors to architecture, and does not help in building resilient architectures. Consider the following:
- It is not uncommon to find more than one possible implementations of a use case.
- Not all implementations may have the same impact on the structure of the software.
- This goal does not take into the consideration the anticipated needs or constraints of the software.
Therefore, the first phase in designing an architecture is to formulate a set of goals that the architecture should meet in order to satisfy the structural requirements of the software.
Note that the goals of the architecture are not the same as the requirements of the software. While the software requirements focus on the external view of the software, the goals of the architecture capture the long-term requirements of the structure of the software. The goals of the architecture should be such that as long as the architecture meets these goals, the software is more likely to evolve and survive changes during its lifetime.
During this phase, the architect should identify the factors that are likely to affect the structure of the software. These factors include best-case requirements, long-term organizational focus, reuse considerations, technology preferences and evolutions, user wish-lists, and other anticipated changes. The architect should elicit these factors from the various stake holders of the software. Based on these, the architect should formulate a set of goals that the structure of the software should meet.
Note that the rationale behind this step is to predict and account for the evolutionary changes that are expected of the software. Although these goals do not directly influence the use cases of the software, these allow the architect to design an architecture that is more likely to absorb changes without losing the structure.
From Goals to Principles
The second step is to discover the principles that the software architecture should follow in order to meet the above goals. These principles are meant to dictate the design and development process of the software during its lifetime.
As pointed out earlier, it is common to find that a use case may be implemented in more than one ways. As Booch [6] has observed, one of the reasons for inherent complexity of software is the flexibility possible through such implementations. Not all possible implementations of a use case may cause or affect the structure of the software in the same way. While some implementations may alter or break the structure of the software, the others may not. The principles of architecture should guide the designers and developers to find the right implementation of a use case.
The architecture principles may be expressed as certain rules, DOs and DONTs, and guidelines that the designers and developers should adhere to. Note that, the process of enforcing these principles is generally more difficult than discovering the principles. This process requires constant mentoring and policing. This is because of the human/organizational involvement in enforcing these principles. Any changes to the team composition may violate these principles as the team may not realize the philosophy and long-term benefits of these principles.
Integration of Principles and Architecture
The last and the most crucial step is to integrate the architecture principles into the architecture. The purpose of this phase is to remove the necessity of human factor in ensuring that the implemented software follows the architecture principles. With the integration of architecture principles with the architecture, the structure of the software dictates how the software should be changed, what kind of changes are possible, and what kind of changes are not.
This process typically manifests into certain constraints and certain facilities or services in the architecture. The constraints control changes that are detrimental to the structure, while the facilities or services provide for extensions.
But, is it possible to integrate the principles with the architecture? The answer is YES. A architecture integrated with these principle typically uses multiple layers of abstractions, indirections, reflection etc. The amount of integration that can be achieved also depends on the chosen programming languages, and the underlying technology.
Role of the Architect
This section summarizes the activities that the architect should carry out to architectures that defy the architecture paradox. The following are the activities
- Based on an analysis of the given requirements, draw the initial architecture.
- Identify the goals of the architecture.
- Discover architecture principles that let the architecture meet the above goals.
- Refine the architecture integrating the above principles.
- Re-evaluate the architecture for implementing the use cases, and other requirements such as performance, scalability etc. Check if the constraints posed by the integrated architecture affect any of the requirements, and refine the architecture accordingly.
Note that this is a creative exercise, and can not be mandated or driven by a process.
Conclusion
This article poses two questions:
- Why should software architectures be protected?
- Why is it difficult to protect software architectures?
It is necessary to protect software architectures, because it is necessary to protect investments in software. This can be achieved only if the structure of software is resilient to changes, and costs of changes to software are low. Interested readers may also look into Big Ball of Mud, a very revealing article by Brian Foote and Joseph Yoder [7] for a list of common patterns software developers follow to create software systems that are difficult to be changed.
The answer to the second question lies in the conflicts (survival and evolution) that a typical software system is exposed to. This paper terms this as architecture paradox.
How to build resilient architectures that are not trapped in the architecture paradox? The answer may be summarized in four points:
- A software system can defy the architecture paradox, only if the structure of the software can accommodate changes.
- Since anticipated changes are not to be implemented in the software right away, it is necessary to abstract these as a set of architecture goals.
- To realize these goals, it is necessary to devise a set of principles.
- To remove the human factor in enforcing these principles, integrate the principles into the architecture, such that the architecture poses the necessary constraints to protect itself.
It is necessary to reemphasize that this is a creative activity and can not be driven by any process. Added to this, the benefits of this exercise may not be immediate.
References
- Paul Clements and Linda M. Northrop (1996): Software Architecture: An Executive Overview, Software Engineering Institute, Carnegie Mellon University, Technical Report CMU/SEI-96-TR-003.
- Len Bass, Paul Clements and Rick Kaxman (1998): Software Architecture in Practice, Addison-Wesley, Reading, Massachusetts.
- Douglas W. Bennet (1996): Hard Software: The Essential Tasks, Manning Publications Co, Greenwich, Connecticut.
- Brooks F. (1995): The Mythical Man-Month - Essays on Software Engineering (20th Anniversary Edition), Addison-Wesley, Reading, Massachusetts.
- Jim Doble (1997): Change Resilience Patterns in Software Architecture and Design, OOPSLA '97 Workshop on Exploring Large System Issues.
- Grady Booch (1994): Object Oriented Analysis and Design with Applications (2nd Edition), Addison-Wesley, Reading, Massachusetts.
- Brian Foote and Joseph Yoder (1997): Big Ball of Mud, Fourth Conference on Pattern Languages of Programs (PLoP '97/EuroPLoP '97), Monticello, Illinois, http://laputan.org/mud/mud.html.
© Subrahmanyam Allamaraju 1998-2002. All rights reserved.
This document is protected by copyright. No part of this document may be reproduced in any form without prior written permission from the author. This document is for electronic distribution only and should not be stored in electronic forms without prior written permission from the author.
All copyrights and trademarks acknowledged.
Software Architecture for Product Families
Excerpts from chapter one taken from the book "Software
Architecture for Product Families" by M. Jazayeri (bio), A. Ran, and F. van der Linden (bio). © 2000 Addison Wesley
Longman Inc.
Reprinted by permission of Addison Wesley Longman.
In recent years, many important contributions have been made to the study of software architecture. The seminal paper by Perry and Wolf (1992) laid the foundation for the study of the subject. The book by Shaw and Garlan (1996) gives a broad perspective on research contributions aiming at solving difficult problems faced by software architects. The book by Bass, Clements, and Kazman (1998) offers in-depth coverage of software architecture in practice, demonstrating how system-level problems are addressed by experienced software architects working on real projects. Finally, Boehm's work (Boehm et al. 1999) puts architecture in the perspective of the organizations involved in procurement, development, deployment, and use of software, thereby making the architecture correspond to business goals and leading to a win-win situation for all stakeholders.
Here we are concerned primarily with the technical aspects of software architecture unified in a consistent conceptual framework. Probably the first work that addressed this goal specifically was "The 4+1 View Model of Architecture" by Philippe Kruchten (1995) of Rational. This work was in informal circulation from the early 1990s and eventually was published by IEEE Software in 1995.
The 4+1 View model offered a simple and understandable way to think about software architecture of complex systems, by organizing descriptions of software related to different concerns in five categories, called views. The four main views are
- The logical view, which is the object model of the design (when an object-oriented design method is used)
- The process view, which captures the concurrency and synchronization aspects of the design
- The physical view, which describes the mappings of the software onto the hardware and reflects its distribution aspect
- The development view, which describes the static organization of the software in its development environment
Descriptions of software in these four views are illustrated and validated with an additional view that contains selected use cases and scenarios. Each view shows a specific aspect of the modeled system. Until now this has been perhaps the most influential approach in terms of popularity in industry. Naturally, the ARES conceptual framework follows the 4+1 View model in many ways.
Soni, Nord, and Hofmeister (1995) took the subject one step further. After studying a considerable number of software-intensive systems built by Siemens, they identified four different architectural views used by designers to describe the software:
- Conceptual architecture. Major design elements and their relationships
- Module interconnection architecture. Functional decomposition, interfaces, and layers
- Execution architecture. The dynamic structure of the system
- Code architecture. Organization of source code, libraries, and binaries
This work confirmed the need for multiple descriptions of software done from different perspectives and demonstrated that the specific perspectives may be different from the set included in the "4+1" views. In addition, Soni, Nord, and Hofmeister called their views architectures, which may be interpreted as a statement that these are, at least partly, independent models rather than different views on the same thing. The paper, however, does not suggest this interpretation. It analyzes relationships among these views, identifies the concerns addressed by each view, and discusses characteristics of development and delivery environments that influence the designs of the different views. Another important contribution of this work is in identifying the need to partition the architecture of software into infrastructure (technical architecture) and application (business architecture)
Software Architecture: A Tool for Dealing with Complexity
Before exploring the main concepts of software architecture, we wish to state our understanding regarding the primary need for software architecture-the main reason for its existence-including when it is reasonable and necessary to address the architecture of software and when we need to consider only software design, if anything at all.
The general interest in architecture emerged when software built by companies crossed a certain threshold of complexity. This happened across industries sometime between the mid-1970s and mid-1980s. The general situation could be characterized as a loss of intellectual control over the software being developed in industry.
This loss of intellectual control could be recognized from multiple symptoms. A common symptom was monotonic growth of software almost unrelated to added functionality, usually as a result of fear to touch the existing code. Engineers were not sure anymore what any particular part of software was doing-that is, where and how it was used. Any request for change in functionality could be addressed only by adding more code. A very typical symptom of lost intellectual control was integration failure. Multiple poorly understood relationships between different components made integration a never-ending process. Correcting one observed problem inevitably led to the introduction of several new ones. Another common symptom was performance barriers that could not be significantly affected by the use of faster hardware. More precisely, nobody seemed to know which hardware component needed to be faster to improve system performance. One of the most painful symptoms was uncontrollable diversification of software created for different customers or markets. Even though products differed only in small parts of their functionality, there was often a wholly separate version and configuration for each market or customer.
Not everybody, however, lost the intellectual control over software development. Projects and products that retained intellectual control over their software employed a different level of understanding the software-an understanding that could be called architectural. Therefore, study of what software architecture is promised to help software developers regain intellectual control over the development of complex software.
We understand software architecture as a conceptual tool for dealing with the complexity of software. There are several essential sources of software complexity:
- Open-endedness, imprecise specification. It seems impossible in practice to precisely specify the function of software before the software is built.
- Indirectness, intangibility. We don't directly construct the performing system itself. We create source code that will go through a variable sequence of nontrivial transformations to produce the executing system.
- Concurrency of execution. Generally we understand space and spatial relationships better than we understand time and temporal relationships. In addition, programming technology is very much geared toward the step-by-step definition of processes. Many systems built in industry, however, have multiple processors and multiple concurrent threads of execution.
- Concurrency of construction. Another aspect of concurrency is concurrent engineering: We cannot build software sequentially piece by piece; rather, large teams have to build different interdependent pieces concurrently.
- Diversification. In industry, we rarely build one-of-a-kind systems. Usually we build product families or product lines in which each product has different features that need to be provided by a single implementation with a minimal amount of configuration, customization, and rework.
- Size. When numbers of design elements such as functions and classes are measured in hundreds of thousands, a different representation of software is required.
Proper architecture of software should reduce the complexity that results from at least one of these factors
Conceptual Framework for Software Architecture
A conceptual framework for software architecture (CFSA) is the foundation on which software architects base their design decisions. For an organization to be able to influence and/or assess design decisions made by software architects, the CFSA needs to be explicitly defined and actively managed The following concepts underlie the ARES CFSA.
Scope
In most circumstances an architecture is intended for more than one instance of a system. Characterization of the class of systems for which the architecture is applicable defines its architectural scope. There is usually a hierarchy of scopes that play an important role in an application domain, a corporation, a company, a product division, or some such entity. Software architecture should be created for a specific architectural scope, consistently extending the architecture of its enclosing scope, providing context for and constraining the architectures created in its subscopes. Specifying the scope for architecture is an important part of architecture itself.
Concerns
Software architecture can play an essential (and independent) role in software development only if it addresses specific architectural concerns related to system life cycle that are not addressed by other software development functions and activities. These concerns are not necessarily evident from system requirement documents or any other system descriptions. Identifying and documenting architectural concerns and their owners, also called stakeholders, is an important part of software architecture.
Requirements
Architectural concerns should be refined into architecturally significant requirements that are specific in terms of desired system properties and the way in which achieving these properties influences or constrains the architecture.
Component Domains
Software exists in multiple forms simultaneously. Some of the most common forms are source or object code components, executable components, and executing components. There are relationships, but no direct correspondence, among these different kinds of components. Each kind of component forms its own component domain. In each component domain, software architecture (as an approach to complexity) addresses different concerns through independent or loosely dependent design decisions within the component domain. Identifying the component domains relevant in view of architecturally significant requirements is an essential part of software architecture.
Structure
In each component domain, independent architectural structures may exist. An architectural structure is created by the partition of software into components in a component domain and their composition into an integrated whole. Architectural structures should be traceable to concrete system elements, rather than being mere conceptual abstractions. Different architectural structures may be interdependent, but they are not different views of the same entity. Architectural structures are an important part of software architecture.
Views
Architectural views are models of architectural structures or other elements of software architecture. Views are used throughout the architecture life cycle for specific purposes of understanding and analyzing the different aspects of system development and performance. The major characteristic of a view is its purpose and utility. Views are not complete descriptions. In fact, views need to omit otherwise important architectural information in order to be useful for their specific purpose. The major issue with views is consistency with the system rather than completeness. Architectural views are a necessary part of architecture on the way to designing architectural structures and different aspects of system design.
Texture
Recurring microstructure of the software components is at least as important as the system structure. We call recurring microstructure of components texture and consider it an important part of software architecture.
Concepts
From the perspective that considers software architecture to be an approach to dealing with complexity, probably the most important decision is the selection of architectural concepts used to think about the system. The existence of architectural concepts is often taken for granted. As we explain later, however, architectural concepts are not found in the application domain or in the implementation domain, but need to be invented in order to simplify the design, construction, and representation of complex software. All other parts of software architecture more or less directly depend on the invention (selection) of architectural concepts. We consider inventing architectural concepts to be the most crucial part of software architecture
What Is Software Architecture?
The first phase of many new projects developing software-intensive products is the design phase of the system software architecture. Often one of the first steps in this process is building a common understanding among the project members about what software architecture is. Active research of software architecture during the 1980s and 1990s has produced a wealth of definitions that attempt to capture the essence of software architecture by abstraction. Together these concepts yield the following definition:
-
Software architecture is defined as components, connectors, constraints, and rationale.
Intellectually, this definition is quite satisfactory. However, in the context of developing and describing software architecture for a product we need a definition that provides answers to very concrete questions:
- How is architecture related to requirements?
- When is architecture sufficiently understood to proceed with the system development?
- Where lies the boundary between architecture and design?
- Does each product, release, or version have a separate architecture, or should there be just one architecture for all products in a product family, or even in an application domain?
The definition we will give later directly addresses these and similar questions. This definition does not contradict or replace the understanding of representing architecture as components, connectors, constraints, and rationale. It simply puts the emphasis on providing concrete guidance in the process of developing and describing the architecture of software.
First and foremost, architecture is a set of concepts through which we impose order on complexity. The concepts we use to think about software determine what is omitted from consideration and what is emphasized, what is grouped and what is separated. Other, more common expressions of architecture are in most circumstances elaborations done using invented architectural concepts to answer specific questions.
We build software to perform the function specified by functional and quality requirements. Functional requirements specify what software has to do. Quality requirements state how well it should be done. Quality requirements qualify the function in terms of desired performance, availability, reliability, usability, configurability, or integrability of the system. (These are often called "ilities.")
In addition to the explicit functional and quality requirements, well-designed software addresses other concerns that constitute implicit requirements for change, reusability, or other kinds of evolution, interoperability with other systems, and so on.
Even though there may be many different requirements specifying different functionality, qualities, or needed evolution flexibility, only a few representative requirements influence the architecture and thus are architecturally significant. The need to focus on architecturally significant requirements leads to the following definition for software architecture:
-
Software architecture is a set of concepts and design decisions that enable effective satisfaction of architecturally significant explicit functional and quality requirements and implicit requirements presented by the problem and the solution domains.
This definition emphasizes several aspects. First, the reason for software architecture is satisfaction of requirements. Not all requirements are architecturally significant. There are different classes of requirements that must be understood in order to create an architecture. Implicit requirements come from both problem and solution domains. Architecture can only enable the satisfaction of requirements; it cannot guarantee their satisfaction. Finally, this definition does not emphasize structure-related decisions over other kinds of decisions. The reason is that the relative weight of structure-related decisions in real systems could be limited.
To limit the responsibilities of the architecture team, we need to answer the question, Where does the boundary between architecture and design lie? When setting the scope for the tasks of the software architecture group, we need to exclude from architectural concerns detailed design decisions made at the component level. Though such decisions may directly influence the capability of the system to satisfy important requirements, they do not influence the design of other components; thus the cost of revising these decisions is limited. Such issues belong to component design. Therefore
-
Software architecture is a set of concepts and design decisions that must be made prior to concurrent engineering to enable effective satisfaction of architecturally significant explicit functional and quality requirements and implicit requirements presented by the problem and the solution domains.
All successful companies nowadays plan product families rather than single products. Therefore, in practice, software architecture always needs to address product family concerns. Products that perform similar functions and share parts form a product family. Multiple releases of a single product that include the enhancement of either functional or quality features and have to be supported during overlapping periods of time in essence also constitute a product family. The main problem in developing software product families is how to achieve sharing of effort and parts when developing variant products while providing variation in their features and capabilities. Software architecture for a product family must specifically address evolution and diversification of products even if these are not explicitly stated in the requirements.
Some design decisions that affect both the satisfaction of system requirements and concurrent design have to do with software structure. This is the reason that software architecture is often identified with the structure of software. However, not all the design decisions that are essential for satisfying system requirements and enabling concurrent engineering are concerned with the structure. Examples include decisions determining the texture of software that include the selection of major component models, design patterns and pervasive design policies as, for example, flow control, load monitoring, execution tracing and logging. In addition, the selection of implementation languages and platforms, trade-off decisions, and process-related decisions fall in the category of architectural concerns. Therefore, our working definition states the following:
-
Software architecture is a set of concepts and design decisions about the structure and texture of software that must be made prior to concurrent engineering to enable effective satisfaction of architecturally significant explicit functional and quality requirements and implicit requirements of the product family, the problem, and the solution domains
Architecturally Significant Requirements
A common misinterpretation of the connection between solution and problem domains is the belief that architecture is determined by requirements. Consequently, some projects needlessly wait to specify requirements completely before starting architectural design a point that is hard to reach in reality without having a good understanding of architecture.
In other cases, detailed product requirements exist because of standards, for example, and architectural design is expected to address product requirements which is impossible without going into the detail of product implementation. In reality, only a small fraction of product requirements have any influence on architecture. Identifying these requirements is the first step in any architectural work.
Identifying Architecturally Significant Requirements
An important question that needs to be answered by a CFSA is how architecturally significant requirements can be identified. Although the answer to this question is definitely domain-dependent, some general rules do apply. Here are some suggestions for identifying requirements that qualify as architecturally significant requirements:
- Requirements that cannot be satisfied by one (or a small set of) system components without dependence on the rest of the system. These usually include all systemwide properties and quality requirements.
- Requirements that address properties of different categories of components for example, how components are named, or referred to, by other components.
- Requirements that address processes of manipulating multiple components for example, system building, configuring, or upgrading.
- Properties of a product or product family that make it unique, competitive, and worth building. These are the most important architecturally significant requirements.
It is essential to build the product right. It is even more important to build the right product. Boehm describes a process for identifying the right product as defined by success-critical stakeholders (i.e., those stakeholders whose agreement and eventual satisfaction is necessary for the success of the product) (Boehm et al. 1999):
- Identify the success-critical stakeholders.
- Identify the stakeholders' win conditions (i.e., the circumstances under which the stakeholder will be satisfied).
- Identify win-condition conflict issues.
- Negotiate top-level win-win agreements.
- Invent options for mutual gain.
- Explore option trade-offs.
- Manage expectations.
- Incorporate win-win agreements into specifications and plans.
- Repeat steps 1 through 8 until the product is fully developed.
- Confront and resolve new win-lose and lose-lose risk items.
This process offers a good framework for defining architecturally significant requirements for the right product.
Structuring Architecturally Significant Requirements
It is generally accepted that the architecture of software directly affects systemwide properties such as availability, reliability, and security. Well-structured software also supports requirements for change, reusability, interoperability with other systems, and so on. If all different requirements were supported by the same architectural structure, it would be impossible to satisfy them independently. And indeed this is often the case. For example, requirements concerning performance and reliability interact because software execution structure affects both kinds of properties.
Often system requirements may be grouped so that requirements in different groups may be addressed by different and at least partly independent software structures established by partitions of software in different component domains. Such partitions exist simultaneously and often are independent of each other. Here are a few examples:
- We address run-time requirements by partitioning software into execution threads of varying priority (or utility), specifying thread scheduling policies, regulating the use of shared resources, and so on.
- We address change and reuse requirements by partitioning software into modules-substitutable, unit-testable components having well-defined boundaries, predictable interaction with the environment, and minimal, well-specified dependencies on other modules.
- We address portability requirements by defining software layers and establishing the conformance of layers and their interfaces to existing standards.
- We address requirements for independent restart or independent failure modes by partitioning the software into a set of separately loadable and executable processes.
Architecturally significant requirements must be grouped so that requirements in different groups may be satisfied independently. Requirements within each group may interact and even conflict. A good rule of thumb for finding independent requirements is to group them by the time of the software life cycle they address. Very often requirements that address software development and change can be satisfied almost independently from requirements that address run-time behavior or software upgrade, for example. We will discuss this in more detail in connection with different software component domains (see Section 1.7).
The number of architecturally significant requirements in each group should be small, from three to five. Whenever possible, architecturally significant requirements in each group should be prioritized
Architectural Structures
A structure of software in a component domain is created by a partition of software into components and their composition into an integrated whole. For every system it is necessary to determine which structures of software affect architecturally significant requirements and to group the requirements in such a way that each group is supported primarily by independent structures that exist in different component domains.
One effective way to identify independent (or partly independent) requirements is by different stages of software life cycle with which they are concerned. A typical (though somewhat simplified) set of stages when different structures of software play major roles includes write time, build time, configuration time, upgrade time, start time, run time, and shutdown time. The most important software structure at write time is the structure of modules. Thus write time-related requirements, such as feature addition and evolution, porting, and diversification, are addressed primarily by appropriate module structures that play a major role at write time.
Similarly, start time-related requirements (such as order, presence, independent operation, and failure modes) are addressed primarily by appropriate executable structures-the startup or shutdown unit or component. In addition, of course, run time-related requirements, such as performance or availability, are addressed by the structures of objects and execution threads-the domain of run-time software components. Table 1.1 lists some of the most common partitions, along with their requirement and component domains, and the software life-cycle stages concerned.
Many projects make the mistake of trying to impose a single partition in multiple component domains, such as equating threads with objects, which are equated with modules, which in turn are equated with files. Such an approach never succeeds fully, and adjustments eventually must be made, but the damage of the initial intent is often hard to repair. This invariably leads to problems in development and occasionally in final products. We have collected several real-life reports of such developments.
In one case, implementation of a complex functional feature was split between two groups. Two functional clusters were defined, along with the necessary interfaces. Unnecessarily, the modules also ended up in different processes and had to interact at run time using slower interprocess communication mechanisms.
Another example involved a system that was partitioned into a set of distributed processes. The partition was motivated by considerations of required parallelism, availability, and fault tolerance. This partition was subsequently used to allocate additional functionality, which affected resource requirements and timing characteristics, violating the original design. As a cure, non-real-time functionality was allocated to new components. However, because the software architecture was identified with its process structure, these components became independent processes. Consequently, the components had complex interfaces and performance was compromised.
Our current understanding suggests that designing a software architecture must start with specific architectural concerns, specify the partition in different component domains, along with a scheme for integration and coordination of the parts, and explain how this specific partition and the corresponding integration of the software address the specified architectural concerns. Examples of architectural concerns may include timeliness, capacity, availability, effective division of work, conformance to standards, use of existing parts, or controlled propagation of change. To address these concerns, different partitions may exist in different component domains.
From the point of view of software reuse, architecture that separates concerns pertinent to different requirement and component domains also results in more reusable components. Therefore it is important to recognize multiple software existence planes (as described earlier in this chapter), with the associated component domains and independent partitions of software, and their relations to different requirement domains.
Architectural Views
Multiple architectural structures should not be confused with architectural views. Architectural structures are concrete and different from each other. Architectural views are abstractions, and different views may be different abstractions of the same entity. Take, for example, layers and subsystems-two commonly used architectural views of software. Subsystems are essentially groupings of modules and are best described by specifying the modules they contain. Subsystems are commonly vertical sections; that is, they usually aggregate modules that implement related functions. (We refer to these later as clusters of functionality.) Layers are horizontal sections that may have different scope within the system. Layers may be confined to a single subsystem or even a part of the subsystem, or they may extend right across different subsystems.
Layers may be established to address portability requirements by requiring conformance to a set of interfaces specified by existing standards. A related view that employs layering is used to manage incremental implementation and functionality delivery. The increment view shows software development increments that can be used for early system integration. This (usually) layered view of system functionality may cut across multiple subsystems.
These three cases (1) subsystems, (2) functional or portability layering, and (3) layers of incremental development-represent views of module partition. It is important to understand this to avoid conflicts in description and update through views.
Architectural views play the same role in dealing with architectural information as data views play in database management systems. We can better understand the value and limitations of architectural views using the lessons learned about data views in the database community. There are two major issues with data views: maintenance and update. View maintenance includes processes for ensuring consistency of the view with the data (and transitively consistency of multiple views). View maintenance may be difficult, but it is feasible and practical as long as view derivation from the data is not too complex. On the other hand, update of data through views is attractive but in general does not work.
These conclusions influenced to a significant degree our understanding and use of architectural views in the ARES project. We understand views as presenting information derived from concrete architectural structures. Views are defined by the derivation procedures, rather than by the information they present. Views can be sketched to understand the architectural structures before they are designed. Once architectural structures exist, views can be changed only after the change is effected in the corresponding architectural structures. For example, we often need to describe interfaces provided (or required) by a certain layer or subsystem. Remember that these interfaces are derived as interfaces of the modules included in the layer or the subsystem.
The term "architectural views" is commonly used to mean a broader category of architectural descriptions following the well-known work of Philippe Kruchten on the 4+1 View model of software architecture. In the 4+1 model, views denote different areas of concern and categories of descriptions rather than views in the sense of abstraction of information regarding concrete architectural structures of software.
There are several good reasons to clearly separate concrete software structures that exist in different component domains from abstract views necessary for managing specific concerns, such as work division, incremental integration, or portability. Whereas the conceptual architecture and architectural views of software may need to be built prior to more detailed design, concrete architectural structures are best described along with detailed design and often after implementation is completed. In addition, the degree of detail and precision in describing conceptual models, architectural views, and architectural structures is different. Finally, it is significantly easier to communicate to software developers the importance of concrete architectural structures than it is to convey abstract conceptual models or architectural views. Understanding the relationships among conceptual architecture, architectural views, and concrete architectural structures makes the architecture more accessible to the development team and thus increases the expected lifetime of the architecture
Texture of Software
The texture of software is created by recurring (uniform) microstructure of its components. Certain aspects of software functionality are hard to localize using common programming languages and techniques. Such functionality cannot be implemented once and then used in different components; rather it must be implemented multiple times. This fact raises the importance of choices and consistency in the implementation of such functionality so that it becomes a major part of the software architecture. Decisions that affect the texture of software have a significant impact on the system, and they are as hard to revise as decisions regarding the structure. Consistency of the texture is very often a problem because the decisions appear to be local to component, cluster, or layer design. It is not easy to identify the common concerns present in the implementation of different components without concentrating on the texture of the software.
Well-designed software has consistent texture. Software components need to observe policies for security, flow control, overload control, and fault detection and handling; they must rely on infrastructure for communication, coordination, state maintenance, execution tracing, and so on. To achieve consistency in component design, the architecture should provide the necessary information. This information can be provided in the form of aspects, policies, and patterns-each of which we examine in more detail in the discussion that follows. The texture of software is created by a combination of observed standards; uniformly applied styles, patterns, and policies; and the use of specific infrastructure, component models, and even programming languages. Examples of software texture that must be designed and regulated by rules and standards include uniform component model realization, error reporting, exception identification and handling, and execution tracing mechanisms
Final Remarks
Separation of concerns is one of the most basic principles of software design. A good conceptual framework for software architecture should support the separation of concerns addressed by software components. This was the main motivation behind the design of the ARES CFSA. The main ideas of our framework are the following:
- Architecturally significant requirements should be identified and managed separately from product requirements. They should be grouped in a way that allows independent satisfaction of requirements in different groups.
- Conceptual architecture is a model of key concepts rather than a blueprint for software construction.
- Software is not a single entity. It exists simultaneously in multiple planes, each having its own component domain. Partitions in different component domains should be established independently, each addressing a different group of architecturally significant requirements.
- Multiple intermediate functionality layers need to be established between the application domain function specified by requirements and the functionality provided by hardware. In the write plane, software components should not span multiple functionality layers.
- Within each functionality layer, multiple functionality clusters can be defined to form natural boundaries within which components are identified, developed, and maintained.
- Consistency of software texture is achieved by defining in the architecture the common aspects that need to be addressed in the design of all components. For each aspect, the architecture needs to specify systemwide policies and patterns of component microstructure that address typical concerns and problems associated with this aspect of component design.
- Software architects should identify and define the set of architectural scopes relevant for the specific system. Architectural decisions and descriptions should be allocated to a well-defined architectural scope. Each software component should belong to a specific architectural scope that determines the scope of its intended reusability and the scope of allowed dependencies.
(end)
Multi-Paradigm Design for C++
James O. Coplien (bio),
Multi-Paradigm
Design for C++, page 6. © 1997 AT&T.
Reproduced by permission
of Addison Wesley Longman. All rights reserved.
Architecture is the primary output of design. It is the articulation of the things of interest in the system and the relationships between those things. Things may be objects, tuples, processes, and other individually comprehensible chunks that figure prominently in the designers vocabulary and toolbox. For example, in a finite-state machine (FSM), these things include states, transitions, transition actions, messages, and the machines themselves. The context-free word thing is preferable to abstraction because the pieces may not be abstract at all, but rather concrete and complete. Such things may be logical architectural artifacts that lack physical continuity in the source or in memory: An example of this is a process, which comprises procedures scattered all over a program.
We usually associate the informal term structure with architecture. System structure emerges from the building blocks we put into it and how we put them together. Both the selection of the blocks and their arrangement follow the desiderata and constraints of the problem statement. The architecture helps us understand that the design process addresses the problem. Multi-paradigm design helps us choose building blocks well-suited to the available solution structures and guides the synthesis of those blocks into a complete system.
An architecture usually corresponds to a domain, an area of interest for which a system is being built. A domain may be hierarchical, which means that architectural models may also be hierarchical.
James Madison and the Role of the Architect
Dana Bredemeyer (bio),
Bredemeyer Consulting
Email: dana@bredemeyer.com
Copyright 2000 by
Dana Bredemeyer
James Madison is called the father of the United States Constitution. It is also appropriate to call him the architect of the Constitution. He was the chief architect in the effort that defined the architecture of the federal government of the United States: the roles and responsibilities of it's branches, the relationships between them, and the principles and mechanisms guiding their implementation, operation and evolution.
The constitution, in just a few pages, defined a stable and flexible system. It has lasted over 200 years and been the model for numerous other constitutions, and it has been changed 27 times.
Madison was guided by a set of values expressed in the preamble to the Constitution:
-
"We the people of the United States, in order to form a more perfect union, provide for the common defense, promote the general welfare, and secure the blessings of liberty to ourselves and our posterity, "
These values were not new, but his vision to realize them was new. From his thorough study of governmental forms throughout history, Madison saw clearly that a governmental structure that would resist the tendencies toward tyranny demanded a structure and mechanisms to keep power distributed. Tyranny was the likely result of unchecked, concentrated power. To define a governmental structure that supported the values expressed in the preamble, and particularly to ensure against tyranny, he articulated two central principles, the separation of powers, and checks and balances. Distribute power, and keep it distributed.
Separation of powers led to the creation of distinct governmental branches with specific responsibilities assigned to them alone. Checks and balances led to the creation of interaction mechanisms to keep power from becoming concentrated in any of the separate branches. The president can veto legislation. The legislature must advise and consent to certain presidential appointments. The courts can declare legislation unconstitutional.
Success depended on much more than understanding governmental structure. Madison needed to change minds. The architect leads from an overall vision. Madison had such a vision entering the Constitutional Convention in 1786, already articulated in the Virginia Plan, which formed the basis of the Convention's deliberations.
On the value of liberty they all agreed. But Madison's plan to achieve it was radical, replacing the weak confederation of independent states with a strong union led by a powerful national government with powers to tax, raise an army, and veto acts of states. His challenge was to associate a shared set of values with a specific proposal for a national government that embodied them, and to do that strongly and vividly enough to overcome deep resistance. The separation of powers was not popular among the American states after the revolution. Legislatures in most states had all the power, leading to abuses of power similar to Colonial rule under the British. Additionally the states were generally not supportive of a strong central government. Madison was moving people from a state-centric to nation-centric view. In the larger and more complex union of states, liberty needed to be designed in at the national level, and this required the states to become less independent, more interdependent.
Approval at the Constitutional Convention was just the beginning. The constitution still needed to be ratified by the states. Working with John Jay and Alexander Hamilton, Madison wrote the Federalist Papers, 85 arguments in favor of the Constitution, published individually in newspapers over the next three years. Anti-Federalists mounted a strong campaign against ratification, and the Bill of Rights was added in response to some of their concerns. Finally only Rhode Island held out, and ratified only when the other twelve states threatened a trade war.
Madison had established and shared a clear vision. He understood the problems of governmental structure, and he took responsibility for the problem from vision through implementation. He provided strong motivation and rationale for the approach he proposed, and he argued persuasively, persistently and passionately until the constitution was fully ratified. His work has survived and guided a nation for two centuries, virtually unchanged.
Acknowledgments
Bill Crandall, of the Product Generation Solutions consulting group in Hewlett-Packard originated the idea of using James Madison and the creation of the U.S. Constitution as a metaphor in our software architecture workshops. Since then, I have done a fair amount of reading about Madison and the Constitution, and the metaphor has grown in richness as my understanding and models of software architecture and the role of the architect have matured. Thanks Bill!
Thanks also to Rand Barbano and others in the HP Product Generation Solutions group (previously called the Software Initiative) for teaching me the value of stories as a medium for instruction. We tell this story, and many others, in the software architecture workshops. Like all good stories, they bear hearing again and again, for there are always new interpretations and relevancy's to find.
References
Crandall, Bill, "James Madison, Architect," Fusion
Newsletter, May 1997.
Rakove, Jack N., Original Meanings, Alfred
A. Knoph, 1996.
Rakove, Jack N., James Madison and the Creation of the
American Republic, 1990.
The Tao of the Software Architect
Lao-Tsu, revisited by Philippe Kruchten (bio)
|
Philippe Kruchten |
650 West 41st Avenue Suite 638 |
This is a very liberal reading of Lao-Tsu's Tao Te Ching for the use of software architects, based on various French and English translations. The number refers to the original tablets.
The architect observes the world but trusts his inner vision. He allows things to come and go. His heart is open as the sky. (12)
The architect doesn't talk, he acts. When this is done, the team says, "Amazing: we did it, all by ourselves!" (17)
When the architect leads, the team is hardly aware that he exists. Next best is a leader that is loved. Next, one who is feared. The worst one who is despised. (17)
A good traveler has no fixed plans and is not intent upon arriving. A good artist lets his intuition lead him wherever it wants. A good scientist has freed himself of concepts and keeps his mind open to what is. Thus the architect is available to everybody and doesn't reject anyone. He is ready to use all situations and does not waste anything. This is called embodying the light. (27)
If you want to shrink something, you must first allow it to expand. If you want to get rid of something, you must first allow it to flourish. If you want to take something, you must first allow it to be given. This is called the subtle perception of the way things are. The soft overcomes the hard. The slow overcomes the fast. Let your workings remain a mystery. Just show people the results. (36)
When the process is lost, there is good practice. When good practice is lost, there are rules. When rules are lost, there is ritual. Ritual is the beginning of chaos.*(38)
The architect concerns himself with the depth and not the surface, with the fruit and not the flower. (38)
The architect allows things to happen. He shapes events as they come. He steps out of the ways and let the design speak for itself. (45)
The architect gives himself up to whatever the moment brings. He knows that he is going to leave, and he has nothing left to hold on to: no illusions, no resistance in his mind. He holds nothing back from the project, therefore is ready for departure, as a man is ready for sleep after a good day's work. (50)
The great way is easy, yet programmers prefer the side paths. Be aware when things are out of balance. Remain centered within the design. (53)
The architect's power is like this. He let all things come and go effortlessly, without desire. He never expect results; thus he is never disappointed. He is never disappointed, thus his spirit never grows old. (55)
Those who know don't talk. Those who talk don't know. (56)
Alternate:
Those who do not have a clue are still debating about the process. Those who know, just do it. (56)
The architect is content to serve as an example and not to impose his will. He is pointed, but doesn't pierce. Straightforward, but supple. Radiant, but easy on the eyes. (58)
If you want to be a great leader, stop trying to control. Let go of fixed plans and concepts and the team will govern itself. The more prohibitions you have, the less disciplined the team will be. The more coercion you exert, the less secure the team will be. The more external help you call, the less self-reliant the team will be. (57)
-----------------------------------------
* Sounds a bit like the SEI CMM! Jim Archer said: "First you pay for results, Then you pay for effort, Finally you pay for attendance."
Especially when he's only a Rational consultant.
Characteristics of an Organization with Mature Architecture Practices
Joe Batman
Software Engineering Institute
- Introduction
When looking at an organization and its products to determine the role that architecture plays in that organization it is necessary to examine both the products, to assess how architecture contributed to their development, as well as process and organizational factors. As systems become larger and more complicated architecture assumes a more important role than has traditionally been the case. Exactly how organizations make use of architecture is an important indicator of their success in developing complex systems that meet requirements in a cost efficient manner. A product line, with its heavy reliance on reuse of common assets, is very dependent upon establishing an effective architecture as the foundation for the products and their management. Architecture, as we are using it here, serves the role of a building plan for a system or set of systems. It is a specification describing how the system is structured and how the parts of a system coordinate their activities. It is, in large part, a set of design decisions made by senior designers, or architects, that address important system-wide issues. It is the set of decisions that the architect has made to guarantee that the system elaborated from the architecture will successfully satisfy those important issues regardless of how low level design decisions unfold, providing the architectural specification is complied with. Effective use of architecture as a means to reduce and manage system complexity appears to depend rather heavily on the use of prescriptive architectures, that is, architectures that serve as specifications for system development and constrain developers with regard to certain important system issues. Many traditional system architectures are what is sometimes termed descriptive architectures, that is, the architectural documentation (if available) describes the structure of a system at some point in time as it is understood by the document writers. Usually, this describes the system as document writers think it is built. However, descriptive architectures do not serve effectively as blueprints for system development. Many systems, in fact, have no architectural documentation although they certainly have architectures, the nature of which may or may not be known. We consider these to be descriptive by default. Descriptive architectures are really the result of the collective actions and design decisions of all of the developers (including design decisions made during integration necessitated by discovery of defects) and are an emergent property of the system. They are not used as a plan for constructing the system that guides and constrains developers in making their design decisions.
Prescriptive architectures are so important because they directly attack the problem of how to insure that system concepts are created that are effective in reducing complexity and abstracting system characteristics so that human designers can retain intellectual control of the artifact they are creating. This intellectual control relies on the ability to understand the gestalt of a system by having a manageably small number of simple models that embody widely used patterns of structure and coordination throughout the system. These patterns are selected on the basis of domain characteristics, system goals, and engineering judgment on those issues that are deemed critical to system success. An example of the effective use of architecture is in planning military operations. It would be impossible for human commanders to reason effectively about a task force they were to command if the units involved did not have prescribed archetypal organizational structures with capabilities and limitations prescribed by tables of organization and equipment, standardized training, and uniform doctrine and policy. If each unit had a unique internal structure, different equipment, unique command structures, different communications methods, etc., it would be impossible for a commander to plan their use with any assurance that the plan was feasible for any but the smallest organizations. At some point the uniqueness of each of the units overwhelms the ability of a human to understand or deal with the collective behavior of the task force. Although units vary because of individual soldier's capabilities, unit strength, and equipment readiness they vary within certain prescribed and well-understood limits.
If we are investigating the feasibility of creating systems with high levels of reuse or establishing a product line then how an organization deals with the issue of architecture is of signal importance. Two areas of particular interest are: the current state of architectures in use or development that can be a basis for constructing a product line and the sophistication or maturity of the organizations that will be developing product line assets. In the following section we will discuss the sort of things we expect to see in promising architectures and the organizations that are capable of creating them.
- Issues of Interest for Architectures
Characteristics of an Effective Architecture
The first area to be investigated is the architecture or architectures that vendors have already fielded in existing products or are developing for imminent release in products. These architectures may fulfill the requirements for a product line or may be a basis for defining such an architecture. Additionally, the existing products or components are potential candidates for inclusion in any subsequent product line. We look, in particular for the following characteristics:
- Use of the architecture as a prescriptive plan for construction of the system. Effective use of architecture is indicated by the creation of a plan, addressing critical system-wide issues, for structuring the resulting system and then developing the system in compliance with that plan. Thus, most effective architectures are defined prior to detailed development and constrain detailed design. They carry the decisions made by the architect and disseminate those decisions to developers.
- There must be clear identification of structural patterns and coordination patterns that abstract important characteristics of the application domain. The architects must clearly identify a small number of key patterns of structure that are sufficient for implementation of the system. These structural patterns are templates for the organization of the system and elaboration of its components. They must be clear and understandable with minimal complexity and the number of patterns must be relatively modest. Each pattern, to be effective, must leverage a substantial portion of the system's organizational structure. They serve to reduce the variability of design across a system while clearly identifying the anticipated locations for variation. The reduction of variability minimizes the complexity of the system allowing more effective reasoning about the system as a whole based on the understanding of the characteristics of a small number of repeating patterns. They also facilitate the standardization of infrastructure services and common utilities and provide a consistent context for components that increases component reusability. The notion of leveraging system understanding from the characteristics and properties of a small number of archetypes applies equally to coordination of activities in the system. These coordination patterns or protocols characterize the interactions that are permitted between components of the system and, again, allow designers to leverage understanding of how the system's components dynamically interact by understanding of the properties and behaviors of a small number of coordination protocols. Each interface in the system is mechanized with one or more of these coordination protocols. The architecture usually embodies these coordination patterns in infrastructure capabilities that are made available for use by the various system components.
- Architectures must provide identification of partitions within the system. A primary division is that between system infrastructure and the applications. The architecture must clearly identify the existence of a system infrastructure, defined in detail by the architecture specification, and the existence of the system applications, parts that implement the mission specific functionality of the system. Infrastructure is ubiquitous and provides capabilities to all applications uniformly. The architecture specification identifies the details of infrastructure design and characteristics, including the interfaces used by applications. This gives an unambiguous picture of what system capabilities are provided as common services to the application developers and allows them to focus on application related details and not be diverted by functionality required to integrate their components into the system. Further partitions are identified within the infrastructure to organize the system wide capabilities and allow efficient allocation of requirements related to common services and overall integration of the system. Applications partitions are also identified along with the allocation of functional requirements to them. This represents the first mechanism for validating the coverage of system requirements. Application partitions provide placeholders for mission specific functionality defined by the application developers.
- Partitions are a way of ordering a system in its decomposition. There are a great many ways of organizing solutions to a design problem but partitions are not arbitrary. We generally expect tighter cohesion and coupling among components within the same partition than between components across partition boundaries. Partition boundaries are often a location where architectural constraints govern the interaction of components. Tighter cohesion between the functions allocated to a partition allows for components within a partition that are more tightly focused on a specific set of application capabilities and helps reduce the number of interfaces required within partitions and between partitions. Partitions do not necessarily reflect the physical model of the system or structure of compilation units.
- An architecture must identify interfaces between the target system and external systems and major and critical interfaces within the target system itself. Architectural views should be provided that illustrate the interfaces and identify those infrastructure capabilities (and the coordination patterns they implement) used to mechanize each interface. Architectural views for a reference architecture will identify the external and component level interfaces by specific details where known and by abstractions where they are determined by target system elaboration. Target architectures will provide specific details of interface content.
- The architectural specification should fully characterize interface mechanisms so that infrastructure developers will know what to build and application developers will know what capabilities are available and how to use them.
- The architectural specification should identify common services and utilities, other than interface mechanisms, that the infrastructure will provide. The specification should describe how they are used, what their intent is, what assumptions are incorporated in their design, and the details of their interface. The architecture should identify system states and modes and describe what each component is expected to provide to support those states and modes and what general behaviors they can expect from the system in each state and mode.
- The development environment in support of the architecture should provide structural types used for component construction. Structural types are a realization of structural patterns identified during architectural design and embody the coordination protocols supported by the infrastructure. They identify locations where developers must provide functionality and where development tools or templates provide default capabilities. Each component of the system is an instance of a structural type defined by the architecture. The environment may provide special tooling, component templates, or instruction guides for developers to use in instantiating these types.
- The architectural design must provide an effective information protection strategy to encapsulate components, infrastructure, and external interfaces. This protection strategy supports a decoupling of components from the implementation details of other components and external systems. Within the constraints of performance requirements this is one of the most important properties enforced by an architecture. It ensures conceptual integrity by managing proliferation of complexity and allows abstraction of stereotypical behaviors. It is a major contributor to the ability of the architecture to provide intellectual control over the system. It insures against side effects and hidden interfaces. An effective information protection strategy has a major impact on the integrability and maintainability of the system as well as on its reliability. We look for protection from the specific details of system components such as operating systems, file management systems, database management systems, hardware devices, inter-process communications facilities, and user interfaces.
- Architectures should isolate system components from the environment in which they operate as far as is feasible. Application components should not be tasked with dealing with contention for system resources, determining communications routing, or maintaining a model of the location of other system components, except where unavoidable.
- The architecture should provide an explicit description of the assumptions built into the architecture including those required by the infrastructure. It should further provide a detailing of the assumptions that components make that effect the interfaces in which they participate. Knowledge of the assumptions used in constructing system components is invaluable in being able to integrate the system in a timely and cost effective manner and in maintaining the system over its lifetime.
- The architecture should support the incremental addition of system capability. The infrastructure should support incremental development allowing new functionality to be added without requiring changes to existing functionality or without requiring extensive retest of previously integrated components. Incremental development facilitates integration, parallel development of system components, and testing of components as black boxes. This reduces the need to retest components when changes are made to implementations or when common components are incorporated into other products.
- The architecture should provide instructions and guidelines for detailed decomposition and lower level partitioning by developers during detailed design. These should be based upon a comprehensive approach to