Component- and Interface-Based Design

Benefits and Challenges of System Integration/Reuse

In engineering circles advances in computer hardware and engineering applications software are driven by market competition, and the desire to design, analyze, and manufacture increasingly complex engineering systems. Complexity can be due to the mere size (or number of parts) of the system, or perhaps due to enhanced performance specifications achieved through the use of new materials, and novel combinations of disciplines (e.g., design and optimal control of electro-mechanical systems).

For organizations that have made large investments in hardware/software technology, there is great reluctance to discard it simply because a new technology has come along. What management would like to see instead, is the benefits of improved communications without having to reinvest in the basic application-specific software. The objectives of systems integration are to try to bring this situation under control, to ensure that the pathway forward maximizes return for the organization, and protects a companies past investments in software and hardware (East, 1994).

What is Reuse?

If systems engineering developments for multidisciplinary engineering and business applications are to have any chance of keeping up with advances in computer hardware and networking, while also achieving significant improvements in system development productivity, one of the most important catalysts is to stop developing system components from scratch for each new project.

Instead, engineering systems should be built from existing application-area components by assembling and replacing inter-operable parts. What is needed are ensembles of business components/objects that provide major chunks of engineering/business functionality, which can be snapped together to create complete business applications.

[Reuse Model]

Figure 1. Models of Reuse -- Cut-and-Paste versus Import

The simplest form of (software) reuse is "cut-and-paste," where chunks of code are cut from an existing work and pasted into a new development. While this form of reuse accelerates the initial design, there are serious problems and limitations in its use. First, adapting a component via cut-and-paste is difficult because you must first look inside (and understand) the component's inner workings before making the modifications. Over time, a library of reusable components can be constructed.

For this approach to development to work(i.e., use of unaltered components applied across many contexts). systems must be sufficiently decoupled so that they can be easily pulled apart, reconfigured, and maintained. Every component should be open to extension, but closed to modification. This is design for reuse in action.

This style of design requires extra decisions on how functionality should be distributed among the system components -- in return, and if this is done well, enhanced flexibility can result from the application of object-oriented principles (D'Souza et al., 1998).

Experience. Decades of experience from the software industry indicate, that this goal is much easier stated than achieved. The main criticism of the the modularity practice to date is due to the narrowness of the domain, which can be largely attributed to:

  1. Poor understanding of the modularity issue;
  2. Lack of theory and tools for the definition of modules from a broad perspective;
  3. Some designers' skepticism of the advantages of modularity, perhaps because benefits have not already been demonstrated.

It takes effort to work out how to make a component more generic. Perhaps the generic component will run more slowly than an application-specific component. The benefit lies in cost savings through increase reuse, reduced maintenance, improved quality and extended working lifetime. The extent to which these benefits will occur, in practice, may be quite uncertain, so generalizing components for reuse is a calculated risk.


INTERFACE-BASED DESIGN

Well-defined interfaces are an essential component of system-level design. Interface-based design is a methodology that employs component interfaces as the key design abstraction, separates system interfaces from the internal details of implementation for virtual components (VCs), and shows how the interfaces at various levels of abstraction relate to each other.

This approach to development encourages designers to:

  1. Consider system behavior more abstractly;
  2. Define independent suppliers of services;
  3. Describe collaborations among services to enact scenarios;
  4. Develop reuse design patterns for familiar situations of component use.

The advantages of this methodology include:

  1. Improved comprehension of the virtual component itself by allowing system integrators to see the "functional" interfaces of a component, without needing to look at internal details.
  2. It assists in the development of virtual components themselves by enabling comprehension of the intent of integration, independent of final utilization.
  3. Mappings between levels of abstraction help to alleviate integration and verification problems because a path is provided to show why interface details are necessary at all levels of abstraction.
  4. Separation of the interface from the system behavior description provides protection for the virtual component maker since details of the internal component workings need not be exposed.

Interfaces can be defined through port definitions (a port is simply a connection point into a virtual component), interface behavior (a description of allowable activity/transactions through a port), attributes (i.e., data attributes; flow of control) and transactions and messages.

Components, Connections and Pluggable Reuse

We define a component as (Brown, 2000):

Components are self-contained packages of functionality that have clearly defined open interfaces that offer "plug-and-play" high-level application services, a specification of external behavior provided and required, plus the documents and source code associated with satisfying the specification (of course, the latter may be withheld from the customers). The elements of a component are (pg. 82; Brown, 2000):

  1. A Specification

    The specification is an abstract description of the services offered by the component. This description may include the expected behavior of the system for specific situations.

  2. One or more Implementations

    Multiple implementations can improve the flexibility for when the component can be used (e.g., across operating systems).

  3. A Constraining Component Standard

    A component model is a set of services that support the system operation, plus a "set of rules" that must be obeyed by an external component for it to take advantage of the services (e.g., CORBA component standard; Javabeans)

  4. A Packaging Approach

    Components can be grouped in different ways to provide a replaceable set of services. This grouping is called a package.

  5. A Deployment Approach

    Once a package of components is installed in an operational environment, they will be deployed.

Using formal specifications to represent hardware/software components facilitates the determination of reusability because they more precisely characterize the functionality of the hardware/software, and the well defined syntax makes processing amenable to automation.

The component approach to development mandates that there is no need to modify a component when it is connected to other components. Generic components have plug-in points (parameterized aspects that can be filled in appropriately in a given context) for implementation of components and for generic model components that are build to be adapted and reused.

[Reuse Plugins]

Figure 2. Plug Points for Plug-ins

Reuse requires that components be built to serve dual purposes. First, they need to be generic -- that is, their properties are not overly tied to a specific application. And second, they must be capable of being easily adapted and customized to the needs of a specific application. So how to:

  1. Implement generic or incomplete problem specifications;
  2. Customize generic implementations to needs of a specific application.

The first item says that we need to apply reuse at all levels of abstraction in the development process, from high-level specifications down to low-level details (see the adjacent figure). The second item says that we need easy to use mechanisms for extending and customizing system modules/components.

Use of Upper and Lower Interfaces

Through the use of well-defined interfaces, components should simply plug together. (insert material from pages ....395.)

[Reuse Interfaces]

Figure 3. Use of Upper and Lower Interfaces

Let's look at the problem of plugging components together in a little more detail. In the construction of an engineering system from components, it is useful to partition the component interfaces into two types: (1) those that are designed to support component assembly, and (2) those that are designed for extension and specialization.

  1. Upper interfaces. -- Upper interfaces enable the direct and visible connecting of parts into a system that provides well defined services.
  2. Lower interfaces. Lower interfaces enable a generic component to be specialized with plug-ins that customize behavior to the problem at hand.

Examples of upper interfaces (from the software world) include public operations of a class, APIs of databases, and primary application-specific services. Examples of lower interfaces (from the software world) can be found in web browsers, spreadsheets, graphics packages, .... etc.

Design and Implementation of Generic Components

Development of reusable system components doesn't occur by itself -- it requires effort. From an organizational perspective, resources must be assigned to the development of reusable assets. Along the way, key questions to be addressed include:

  1. Should a component be made sufficiently generic for reuse?
  2. How generic and reusable should it be?

A fundamental tenet of component design is complete separation of the interface specifications (i.e., what a component will provide and expect when used) from implementation. By encapsulating application components/objects with well-defined open interfaces, complexity of system development is held in check because developers only need to know what the object is and the services it provides (i.e., they do not need to understand the internal workings).

[Reuse Model]

Figure 4. Pathway of Development for Reusable Components

The adjacent diagram shows the pathway of development for creation and use of reusable components. There is no magic formula for reuse. If you notice that a large block of system code is being used across a family of applications, it is clearly a candidate for packaging and reuse. This requires careful analysis of the problem domain. There is also a danger of carrying generalization and reuse too far, producing generic components containing many features that are rarely used.

On a larger scale, reuse of components occurring among individuals, design teams and organizations requires coordination. Someone needs to be responsible for the component storage, management and distribution.

To assemble a larger component (or application) from a smaller component, the basic idea in component-based design is to:

  1. Select which components will be used (perhaps from a library of components);
  2. Plug components together by connecting required interfaces of one component to provided interfaces of other components.

Component-Based Design versus Object-Oriented Design

The differences between component-based design and object-oriented design have less to do with either style of design, and more to do with factors of degree and scale. For example:

  1. Components tend to have a richer set of inter-component communication mechanisms, such as events and workflows, rather than just the basic object-oriented message.
  2. Components are often larger-grained than traditional objects, and can be implemented multiple objects of different classes. They often have complex actions at their interfaces (rather than simple messages).
  3. By definition, a component package includes definitions of the interfaces it provides, as well as the interfaces it requires. Traditional interfaces in the object-oriented community focus only the operations provided.
  4. Objects tend to be dynamic -- for example, the number of customers a company may have -- and have dynamic interfaces. Larger grained components, in contrast, tend to me more static and have static configurations.

Compared to objects, components offer the following benefits:

  1. They permit reuse of implementations and related interfaces at medium granularity (i.e., above a single domain object). The resulting service may benefit/affect objects across multiple domains.
  2. Well developed components form the basis for maintenance and upkeep, and allow for incremental replacement as needed. There should be no need to replace a whole system.
  3. Component partitioning allows for parallel development.
  4. Interface-centric designs leads to scalable and extensible architectures. By letting components have multiple interfaces, we reduce the possibility of one component depending on irrelevant features of another component it connects with.

Components need not be assembled from objects. For example, a benefit of component-based technology is that they can be assembled as wrappers around legacy systems. For more information, see "components and connectors, pg. 397."


STANDARDS FOR INTEROPERABILITY

Component specifications contain the following information:

  1. A list of operation names and signatures defining the input and output parameters for each operation.
  2. An informal textual description of the component's functionality, and intended usage scenarios.
  3. An informal description of the component's operating context (e.g., a description for when can the component be used?)
  4. Performance and availability data for typical use/execution of the component.

Together these mechanisms enable communication, which is the key to system interoperability. In present day terms, the telephone is perhaps the best example of a system once dominated by company-specific proprietary standards, now replaced by a common global standard. The result -- anyone can phone anywhere, anytime.

Connector Standards

To facilitate communication among components we define standard kinds of connectors between components:

  1. Connectors that support explicit call and return.
  2. Connectors with explicit event propagation. Certain state changes in one component can be propagated to all components that have registered an interest in that event.
  3. Connectors that directly support streams. Producers insert values (or objects) into the stream, where they remain until they care consumed by other components.
  4. Connectors that support workflow. Objects are transfered between components, where the transfer itself is a significant event.
  5. Connectors that support mobile code. Rather than just receive and send data and references to objects, you can actually transmit an object, complete with the code that defines the behaviors.

For more information, see "components and connectors" page 397.


APPLICATION ASSEMBLY FROM COMPONENTS

The essential elements of component-based design are (see Brown, 2000, pg. 110):

  1. Application assembly from components

    Systems are modeled as collections of interacting components. System behavior is defined and analyzed in terms of component interfaces.

  2. Provision for independent services

    Component functionality should have high cohesion.

  3. A common component infrastructure

    It must be possible to specify and build components independently from one another.

  4. Use of standard services.

To achieve system-level application assembly from components, we need:

  1. A clear separation of component specification from its design and implementation

    This principle allows for orthogonalization of design concerns (e.g., separation of models of behavior from models of system structure).

  2. An interface-based design approach

    System components are defined by encapsulated behavior accessible through well-defined interfaces. Interfaces define the services that can be provided by the component, and the rules under which these services can be provided.

  3. Formally recorded component semantics

    Informal descriptions of component behavior can be provided by way of operation signatures and informal text. However, detailed descriptions of operational semantics require formal, verifiable descriptions using pre- and post-conditions attached to each operation (sounds like UML might be useful here, huh?).

  4. A rigorously recorded refinement process

    This process records the history of development for the component, and includes information to assure quality and aspects of the designer's rationale.

These practices are supported by the principles of orthogonalization of concerns, effective use of languages for system modeling, and formal models for system verification.

Supporting Component Modeling with UML

When designing a system, many of the system's inherent qualities are determined by decisions that lead to what the main functional pieces of the system are (see Brown, pg. 133).

UML diagrams can be used to capture and record the static and dynamic behavior (e.g., activity diagrams, sequence diagrams, statechart diagrams) of a component system.

Specifying Interfaces with Class Diagrams.

See Brown pg's 163-165.


References and Web Resources

  1. Atkinson C., et al., Component-Based Product Line Engineering with UML, Component Software Series, Addison-Wesley, 2002.
  2. Brown A.W., Large-Scale Component-based Development, Prentice-Hall, 2000.
  3. Wallnau K.C., Hissam S.A., Seacord R.C., Building Systems from Commercial Components, Addison-Wesley, 2001.

Developed in February 2001 by Mark Austin
Copyright © 2001-2002, Mark Austin, University of Maryland