Software Product Lines
Framework Home
Introduction
Product Line Essential Activities
Product Line Practice Areas
Software Engineering
Practice Areas
Architecture Definition
Architecture Evaluation
Component Development
Mining Existing Assets
Requirements Engineering
Software System Integration
Testing
Understanding Relevant Domains
Using Externally Available Software
Technical Management
Practice Areas
Organizational Management
Practice Areas
Frequently Asked Questions
Glossary
Bibliography

A Framework for Software Product Line Practice, Version 5.0

Next Section Table of Contents Previous Section

Architecture Definition

This practice area describes the activities that must be performed to define a software architecture. By software architecture, we mean the following:

The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements, and the relationships among them. "Externally visible" properties are those assumptions other elements can make of an element, such as its provided services, performance characteristics, fault handling, shared resource usage, and so on [Bass 2003a].

By making "externally visible properties" of elements1 part of the definition, we intentionally and explicitly include elements' interfaces and behaviors, as part of the architecture. We will return to this point later. By contrast, design decisions or implementation choices that do not have system-wide ramifications or visibility are not architectural.

Architecture is key to the success of any software project. It is the first design artifact that begins to place requirements into a solution space. The quality attributes of a system (such as performance, modifiability, and availability) are, in large part, permitted or precluded by its architecture–if the architecture is not suitable from the beginning for these qualities, don't expect to achieve them by some miracle later. The architecture determines the structure and management of the development project as well as the resulting system, since teams are formed and resources allocated around architectural components. For anyone seeking to learn how the system works, the architecture is the place where understanding begins. The right architecture is absolutely essential for smooth sailing. The wrong one is a recipe for disaster.

Architectural requirements: For an architecture to be successful, its constraints must be known and articulated. And contrary to standard software engineering waterfall models, an architecture's constraints go far beyond implementing the required behavior of the system that is specified in a requirements document [Clements 2002c, p. 57]. Other architectural drivers that a seasoned architect knows to take into account include

Component interfaces: As we said earlier in this section, architecture includes the interfaces of its components. It is therefore incumbent on the architect to specify those interfaces (or, if the component is developed externally, ensure that its interface is specified adequately by others). By interface we mean something far more complete than the simple functional signatures one finds in header files. Signatures simply name the programs and specify the numbers and types of their parameters, but they tell nothing about the semantics of the operations, the resources consumed, the exceptions raised, or the externally visible behavior. As Parnas wrote in 1972, an interface consists of the set of assumptions that users of the component may safely make about it-nothing more and nothing less [Parnas 1972a]. Approaches for specifying component interfaces are discussed in "Example Practices."

Connecting components: Applications are constructed by connecting components to enable communication and coordination. In simple systems that run on a single processor, the venerable procedure call is the oldest and most widely used mechanism for component interaction. In modern distributed systems, however, something more sophisticated is desirable. There are several competing technologies for providing these connections as well as other infrastructure services. Among the services provided by the infrastructures are

These infrastructures, which are purchased as commercial packages, are components themselves that facilitate connection among other components. These infrastructure packages, like patterns, represent another class of already solved problems (highly functional component interactions for distributed systems) that the architect need not reinvent. Market contenders are Sun Microsystems' Java 2 Enterprise Edition (J2EE), including Enterprise Java Beans (EJB) (http://java.sun.com/j2ee), and Microsoft's .NET (http://www.microsoft.com/net).

Architecture documentation and views: In order for an architecture to achieve its effectiveness, it must be documented. Here, architectural views come into play. A view is a representation of a set of system elements and the relationships among them [Clements 2002a]. A view can be thought of as a projection of the architecture that includes certain kinds of information and suppresses other kinds; for example

There are many views of an architecture; choosing which ones to document is a matter of what information you wish to convey. Each view has a particular usefulness to one or more segments of the stakeholder community [IEEE 2000a] and should be chosen and engineered with that in mind.

Aspects Peculiar to Product Lines

All architectures are abstractions that admit a plurality of instances; a great source of their conceptual value is, after all, the fact that they allow us to concentrate on design while admitting a number of implementations. But a product line architecture goes beyond this simple dichotomy between design and code–it is concerned with identifying and providing mechanisms to achieve a set of explicitly allowed variations (because when exercised, these variations become products). Choosing appropriate variation mechanisms may be among the product line architect's most important tasks. The variation mechanisms chosen must support

Support for variation can take many forms (and be exercised many times [Clements 2002c, p. 64]). Mechanisms to achieve variation in the architecture are discussed under "Example Practices."

Products in a software product line exist simultaneously and may vary from each other in terms of their behavior, quality attributes, platform, network, physical configuration, middleware, and scale factors and in a multitude of other ways. Each product may well have its own architecture, which is an instance of the product line architecture achieved by exercising the variation mechanisms. Hence, unlike an organization engaged in single-system development, a product line organization will have to manage many related architectures simultaneously.

There must be documentation for the product line architecture as it resides in the core asset base and for each product's architecture (to the extent that it varies from the product line architecture). For the product line architecture, the views need to show the variations that are possible and must describe the variation mechanisms chosen with the rationale for the variation. Furthermore, a description–the attached process–is required that explains how to exercise the mechanisms to create a specific product. The views of the product architectures, on the other hand, have to show how those variation mechanisms have been used to create this product's architecture. As with all core assets, the attached process becomes the part of the production plan that deals with the architecture.

Application to Core Asset Development

The product line architecture is an early and prominent member in the collection of core assets. The architecture is expected to persist over the life of the product line and to change relatively little and slowly over time. The architecture defines the set of software components (and hence their supporting assets such as documentation and test artifacts) that populates the core asset base. The product line architecture–together with the production plan–provides the prescription (harkening to the "in a prescribed way" from the definition of a software product line) for how products are built from core assets.

Application to Product Development

Once it's been placed in the core asset base for the product line, the architecture is used to create product architectures for each new product according to the architecture's attached process. If the product builders discover a variation point or a needed mode of variation that is not permitted by the architecture, they should bring it to the architect's attention; if the variation is within the product line's scope (or deemed desirable to add to the scope), the architecture may be enhanced to accommodate it. The "Operations" practice area deals with setting up this feedback loop in the organization.

Example Practices

We categorize example practices for architecture definition into those concerned with understanding the requirements for the architecture; designing the architecture; and communicating or documenting the architecture.

Understanding the Requirements for the Architecture

Quality Attribute Workshops: Prerequisite to designing an architecture is understanding the behavioral and quality attribute requirements that it must satisfy. One way to elicit these requirements from the architecture's stakeholders is with an SEI Quality Attribute Workshop (QAW) [SEI 2007g]. QAWs provide a method for identifying the quality attributes that are critical to a system architecture–attributes such as availability, performance, security, interoperability, and modifiability. In the QAW, an external team facilitates meetings between stakeholders during which scenarios representing the quality attribute requirements are generated, prioritized, and refined (i.e., adding additional details such as the participants and assets involved, the sequence of activities, and questions about quality attribute requirements). The refined scenarios can be used in different ways; for example, as seed scenarios for an evaluation exercise or as test cases in an acquisition effort.

Use of the production strategy: The choice of variation mechanisms is strongly influenced by the organization's production strategy. That strategy describes how the organization plans to build the specific products from the core assets. For example, an organization may decide that an integration team will assemble a product by selecting from existing components. This strategy forces the architecture team to focus on component substitution as a variation mechanism. Mechanisms that require additional coding may not be appropriate in this setting.

Planning for architectural variation: Nokia has used a "requirements definition hierarchy" as a way to understand what variations are important to particular products [Kuusela 2000a]. The hierarchy consists of design objectives (goals or wishes) and design decisions (solutions adopted to meet the corresponding goals). For example, a design objective might be "the system shall be highly reliable." One way to meet that objective is to decree that "the system shall be a duplicated system." That, in turn, might mean that "the system shall have duplicated hardware" and/or "the system shall duplicate communication links." Another way to meet the reliability objective is to decree that "the system shall have a self-diagnostic capacity," which can be met in several ways. Each box in the hierarchy is tagged with a vector, each element of which corresponds to a product in the product line. The value of an element is the priority or importance given to that objective, or to the endorsement of that design decision, by the particular product. For example, if an overall goal for a product line is high reliability, being a duplicated system might be very important to Product 2 and Product 3 but not at all important to Product 1 (a single-chip system).

The requirements definition hierarchy is a tool that the architect can use as a bridge between the product line's scope (see the "Scoping" practice area), which will tell what variations the architecture will have to support, and the architecture, which may support the variation in a number of ways. It is also useful to see how widely used a new feature or variation will be: should it be incorporated into the architecture for many products to use, or is it a one-of-a-kind requirement best left to the devices of the product that spawned it? The hierarchy is a way for the architect to capture the rationale behind such decisions.

Designing the Architecture

Architecture definition and architecture-based development: As the field of software architecture has grown and matured, methods of creating, defining, and using architecture have proliferated. Many example practices related to architecture definition are defined in widely available works [Kruchten 1998a, Jacobson 1997a, Hofmeister 2000a, Bachmann 2000a]. The Rational Unified Process (RUP) is a method used for object-oriented systems. A good resource for RUP is the book The Rational Unified Process: An Introduction [Kruchten 2004a].

Attribute-Driven Design (ADD): The SEI Attribute-Driven Design (ADD) method [SEI 2007a] is a method for designing the software architecture of a product line to ensure that the resulting products have the desired qualities. ADD is a recursive decomposition method that starts by gathering architectural drivers that are a combination of the quality, functional, and business requirements that "shape" the architecture. The steps at each stage of the decomposition are

  1. Choose architectural drivers: The architectural drivers are the combination of quality, business, and functional goals that "shape" the architecture.
  2. Choose patterns and children component types to satisfy drivers: There are known patterns to achieve various qualities. Choose the solutions that are most appropriate for the high-priority qualities.
  3. Instantiate children design elements and allocate functionality from use cases using multiple views: The functionality to be achieved by the product family is allocated to the component types.
  4. Identify commonalities across component instances: These commonalities are what define the product line, as opposed to individual products.
  5. Validate that the quality and functional requirements and any constraints have not been precluded from being satisfied by the decomposition.
  6. Refine use cases and quality scenarios as constraints to children design elements: Because ADD is a decomposition method, the inputs for the next stage of decomposition must be prepared.

Architectural patterns: Architectures are seldom built from scratch but rather evolve from solutions previously applied to similar problems. Architectural patterns represent a current approach to reusing architectural design solutions. An architecture pattern2 is a description of component types and a pattern of their runtime control and/or data transfer [Shaw 1996a]. Architectural patterns are becoming a de facto design language for software architectures. People speak of pipe-and-filter, n-tier, client-server, or agent-based architectures, and these phrases immediately convey complex and sophisticated design information. Architectural pattern catalogues exist that explain the properties of a particular pattern, including how well-suited each one is for achieving specific quality attributes such as security or high performance. Buschmann, Schmidt, and colleagues provide examples of catalogs [Buschmann 1996a, Schmidt 2000a]. Using a previously catalogued pattern shortens the architecture definition process, because patterns come with pedigrees: what applications they work well for, what their performance properties are, where they can easily accommodate variation points, and so forth. Product line architects should be familiar with well-known architectural patterns as well as patterns (well-known or not) that are used in systems similar to the ones they are building.

Service-oriented architectures: One architectural pattern that's very popular now is the service-oriented architecture. A service-oriented architecture is one in which the components are services. A service is a reusable, self-contained, distributed component with a published interface that stresses interoperability, is usually thread-safe, and is discoverable and dynamically bound. Service-oriented systems work by "stringing together" services that have specific, well-defined functionality into chains that do sophisticated, useful work. Services can be locally developed or (in theory) "discovered" on a company's intranet or even on the World Wide Web and bound at runtime. Standards exist for services communicating with each other via messaging based on the Extensible Markup Language (XML), for specifying what services do, and for quality-of-service contracts necessary to insure that a service provides the level of functionality and quality attributes required. A service-oriented architecture's basic variation mechanism is component replacement–that is, choosing different services or stringing together services in a different way to meet the needs of individual products.

Aspect-oriented software development (AOSD): AOSD is an approach to program development that makes it possible to modularize systemic properties of a program such as synchronization, error handling, security, persistence, resource sharing, distribution, memory management, replication, and the like that would otherwise be distributed widely across the system, making it hard to change. An aspect is a special kind of module that implements one of these specific properties that would otherwise cut across other modules. As that property varies, the effects "ripple" through the entire program automatically. As an example, an AOSD program might define "the public methods of a given package" as a crosscutting structure and then say that all those methods should do a certain kind of error handling. This aspect would be coded in a few lines of well-modularized code. AOSD is an architectural approach, because it provides a means of separating concerns that would otherwise affect a multitude of components constructed to separate a different, orthogonal set of concerns. AOSD is appealing for product lines, because the variations can often be represented as aspects. A good starting point for understanding AOSD is provided at http://aosd.net.

Mechanisms for achieving variability in a product line architecture (1): Svahnberg and Bosch created a list of variability mechanisms for product lines that includes mechanisms for building variability into components. Svahnberg and Bosch also include these architectural mechanisms [Svahnberg 2000a]:

Code-based mechanisms used to achieve variability within individual components are discussed in the "Component Development" practice area.

Mechanisms for achieving variability in a product line architecture (2): Philips Research Laboratories uses service component frameworks to achieve diversity in its product line of medical imaging systems [Wijnstra 2000a]. Goals for that family include extensibility over time and support for different functions at the same time. A framework is a skeleton of an application that can be customized to yield a product. White-box frameworks rely heavily on inheritance and dynamic binding; knowledge of the framework's internals is necessary in order to use it. Black-box frameworks define interfaces for components that can be plugged in via composition tools. A service component framework is a type of black-box framework that supports a variable number of plug-in components. Each plug-in is a container for one or more services, which provide the necessary functionality. All services support the framework's defined interface but exhibit different behaviors. Clients use the functionality provided by the component framework and the services as a whole; the assemblage is, itself, a component in the products' architecture. Conversely, units in the product line architecture may consist of or contain one or more component frameworks.

Mechanisms for achieving variability in a product line architecture (3): Bachmann and Clements sum up the current approaches for variation mechanisms in product line architectures and sketch an economics-based approach for choosing them [Bachmann 2005a].

Communicating and Documenting the Architecture

Architecture documentation: Recently, in the software engineering community, more attention has been paid to writing down a software architecture so that others can understand it, use it to build systems, and sustain it. The Unified Modeling Language (UML) is the most-often-used formal notation for software architectures, although it lacks many architecture-centric concepts. The SEI developed the Views and Beyond approach to documentation [Clements 2002a], which holds that documenting a software architecture is a matter of choosing the relevant views based on projected stakeholder needs, documenting those views, and then documenting the information that applies across all of them. Examples of cross-view information include how the views relate to each other and stakeholder-centric roadmaps through the documentation that let people with different interests find information relevant to them quickly and efficiently. The approach includes a three-step method for choosing the best views to engineer and document for any architecture, and the overall approach produces a result compliant with the Institute of Electrical and Electronics Engineers' (IEEE's) recommended best practice on documenting architectures of software-intensive systems [IEEE 2000a].

Specifying component interfaces: Interfaces are often specified using a contractual approach. Contracts state pre- and postconditions for each service and define invariants that express constraints about the interactions of services within the component. The contract approach is static and does not address the dynamic aspects of a component-based system or even the dynamic aspects of a single component's behavior. Additional techniques such as state machines [Harel 1998a] and interval temporal logic [Moszkowski 1986a] can be used to specify constraints on the component that deal with the ordering of events and the timing between events. For example, a service may create a thread and assign it work to do that will not be completed within the service's execution window. A postcondition for that service would include the logical clause for "eventually this work is accomplished."

A complete contract should include information about what will be both provided and required. The typical component interface specification describes the services that a component provides. To fully document a component so that it can be integrated easily with other components, the specification should also document the resources that the component requires. In addition, this documentation provides a basis for determining whether there are possible conflicts between the resources needed for the set of components that make up the application.

A component's interface provides only a specification of how individual services respond when invoked. As components are integrated, additional information is needed. The interactions between two components needed to achieve a specific objective can be described as a protocol. A protocol groups together a set of messages from both components and specifies the order in which they are to occur.

Each component exhibits a number of externally visible attributes that are important to its use but are often omitted (incorrectly) from its interface specification. Performance (throughput) and reliability are two such attributes. The standard technique for documenting the performance of a component is the computational complexity of the dominant algorithms. Although this technique is platform independent, it is difficult to use in reasoning about satisfying requirements in real-time systems, because it fails to yield an actual time measure. Worse, it uses information that will change when algorithms (presumably encapsulated within the component) change. A better approach is to document performance bounds, setting an upper bound on the time consumed. The documentation remains true when the software is ported to a platform at least as fast as the current one–a safe assumption in today's environment. Cases in which the stated bounds are not fast enough can be resolved on a case-by-case basis. If the product can indeed meet the more stringent requirement on that product's platform, that fact can be revealed. If it cannot, either remedial action must be taken or the requirement must be relaxed.

Practice Risks

The biggest risk associated with this practice area is failing to have a suitable product line architecture. An unsuitable product line architecture will result in

These effects, in turn, will lead to extensive and time-consuming rework, poor system quality, and an inability to realize the product line's full benefits. If product teams do not find the architecture suitable for their products and easy to understand and use, they may bypass it, resulting in the eventual degradation of the entire product line concept.

Unsuitable architectures could result from

Unsuitable architectures are characterized by

Further Reading

General software architecture:

[Bass 2003a]
Bass, Clements, and Kazman emphasize architecture's role in system development and provide several case studies of architectures used to solve real problems. One is an architecture for the CelsiusTech ShipSystem 2000 product line. Their book also includes an extensive discussion of architectural views.

[Buschmann 1996a] & [Schmidt 2000a]
Buschmann, Schmidt, and colleagues provide excellent examples of architectural patterns.

[Hofmeister 2000a]
Hofmeister emphasizes views and structures and provides a solid treatment of building a system from an architecture and its views.

[SEI 2007b]
The SEI's Software Architecture Technology (SAT) Web site provides a wide variety of software architecture resources and links.

[Shaw 1996a]
Shaw and Garlan provide an excellent treatment of architectural patterns (what they call styles) and their ramifications for system building.

Product line architecture:

[Bosch 2000a]
Bosch brings a dedicated product line focus to the mix. His work is required reading for the product line practitioner.

Software architecture from a strictly object-oriented point of view:

[Booch 1994a]
Booch offers a good foundation for architecture definition.

[Buschmann 1996a]
The work of Buschmann and colleagues raises the design pattern phenomenon to the arena of software architecture and is a good staple in any architect's toolbox.

[Jacobson 1997a]
Jacobson, Griss, and Jonsson devote an entire section to architectural patterns for object-oriented systems designed with strategic reuse in mind.

[Kruchten 2004a]
Kruchten's book is a good source for gaining an understanding of RUP.

[Smith 2001a]
Smith and Williams' book contains three chapters on principles and guidance for architecting systems (object-oriented or not) in which performance is a concern.

Problem solving:

[Jackson 2000a]
Jackson classifies, analyzes, and structures a set of recurring software development problems, organized according to how the software will interact with the outside world.

Architecture documentation:

[Clements 2002a]
Clements and colleagues explain the Views and Beyond approach to architecture documentation.

UML:

[OMG 2007a]
This Web site is the starting point for an investigation of UML.

Next Section Table of Contents Previous Section

 

1 An element is a unit of software that has identity either at implementation time or at runtime. We use the term component to refer to a unit of software that must be developed or acquired as a unit.

2 The term used by Shaw and Garlan was architectural style, which is synonymous with pattern [Shaw 1996a].