Previous Table of Contents Next


2.2.2. Solutions in Patterns and Frameworks

Successful developers overcome the problems outlined previously by identifying the design patterns that underly proven solutions and by reifying these patterns in application frameworks. Patterns and frameworks help alleviate the continual rediscovery and re-invention of communication software concepts and components by capturing solutions to standard communication software development problems (Gamma, Helm, Johnson, & Vlissides, 1995). For instance, patterns are useful for documenting the structure and participants in common micro-architectures such as Reactors (Schmidt, 1995) and active objects (Lavender & Schmidt, 1996). These patterns are generalizations of object-structures that have proven useful in building flexible and efficient event-driven and concurrent communication software frameworks and applications.

Traditionally, communication software patterns have either been locked in the heads of the expert developers or buried deep within the source code. Allowing this valuable information to reside only in these locations is risky and expensive, however. For instance, the insights of experienced designers will be lost over time if they are not documented. Likewise, substantial effort could be necessary to reverse engineer patterns from existing source code. Therefore, capturing and documenting communication software patterns explicitly is essential in preserving design information for developers who enhance and maintain existing software. Moreover, knowledge of domain-specific patterns helps guide the design decisions of developers building new applications.

Although knowledge of patterns helps to reduce development effort and maintenance costs, reuse of patterns alone is not sufficient to create flexible and efficient communication software. Although patterns enable reuse of abstract design and architecture knowledge, abstractions documented as patterns do not directly yield reusable code. Therefore, it is essential to augment the study of patterns with the creation and use of application frameworks. Families of frameworks help developers avoid costly reinvention of standard communication software components by implementing common design patterns and factoring out common implementation roles.

Frameworks provide reusable software components for applications by integrating sets of abstract classes and defining standard ways that instances of these classes collaborate (Johnson & Foote, 1988). The resulting application skeletons can be customized by inheriting and instantiating from reusable components in the frameworks. The scope of reuse in a framework can be significantly larger than using traditional function libraries or conventional OO class libraries because frameworks are tightly integrated with key communication software tasks (such as service initialization, error handling, flow control, event processing, and concurrency control). In general, frameworks enhance class libraries in the following ways:

  Frameworks define semi-complete applications that embody domain-specific object structures and functionality. Class libraries provide a relatively small granularity of reuse. For instance, the classes in Figure 2.1(A) are typically low-level, relatively independent, and general components such as strings, complex numbers, arrays, and bitsets. In contrast, components in a framework collaborate to provide a customizable architectural skeleton for a family of related applications. Complete applications can be composed by inheriting from and/or instantiating framework components. As shown in Figure 2.1(B), this reduces the amount of application-specific code because much of the domain-specific processing is factored into the generic components in the framework.
  Frameworks are active and exhibit inversion of control at runtime. Class libraries are typically passive, i.e., they perform their processing by borrowing threads of control from self-directed application objects. This is illustrated in Figure 2.1(A), where the application-specific logic manages the event loop. In contrast, frameworks are active; i.e., they manage the flow of control within an application via event dispatching patterns such as Reactor (Schmidt, 1995) and Observer (Gamma et al., 1995). Figure 2.1(B) illustrates the callback-driven run-time architecture of a framework. This inversion of control is referred to as The Hollywood Principle (Vlissides, 1996), i.e., “Don’t call us; we’ll call you.”


FIGURE 2.1.  Differences between class libraries and object-oriented frameworks.

In practice, frameworks and class libraries are complementary technologies. Frameworks often utilize class libraries internally to simplify the development of the framework. For instance, portions of ACE use the string and vector containers provided by the C++ Standard Template Library (Stepanov & Lee, 1994) to manage connection maps and other search structures. In addition, application-specific callbacks invoked by framework event handlers frequently use class library components to perform basic tasks such as string processing, file management, and numerical analysis.

To illustrate how OO patterns and frameworks are being successfully applied to communication software, the remainder of this chapter examines the structure and use of the ACE framework (Schmidt & Suda, 1994).


Previous Table of Contents Next