The rules of the game -- patterns and idioms


introduction framework patterns components conclusions references appendix experience
The design of hush and its extensions can be understood by a consideration of two basic patterns and their associated idioms, that is the nested-component pattern (which allows for nesting components that have a similar interface) and the actor pattern (which allows for attributing different modes or roles to objects). The realizations of these patterns are based on idioms extending an improved version of the familiar handle/body idiom. Our improvement concerns the introduction of an explicit invocation context which is needed to repair the disruption of the virtual function call mechanism caused by the delegation to 'body implementation' objects.

In this section, we will first discuss the handle/body idiom and its improvement. Then we will discuss the two basic patterns underlying the design of hush and we will briefly sketch their realization by extensions of the (improved) handle/body idiom.

The handle/body idiom -- invocation context

The handle/body idiom allows for separating the definition of a component's interface (the handle class) from its realization (the body class). All intelligence is located in the body, and (most) requests to the handle object are delegated to its implementation. In order to optimize the creation and destruction of dynamically allocated objects, one may use techniques such as representation or resource sharing and reference counting. However, the use of these techniques can put a heavy burden on the application programmer. The handle/body idiom was introduced in  [Coplien] as a means to hide the use of such low-level issues from the application programmer, by adding a level of indirection, that is delegation to a 'body' implementation object. An additional advantage of applying the idiom is that it allows interface classes to become stable while improving on the realization. In practice, by applying the idiom one may avoid recompilation of dependent code as long as the interface class does not change.

Invocation context

The handle/body idiom is one of the most popular idioms  [Coplien,Eliens95,GOF,Stroustrup,Pree]. It underlies several other idioms and patterns (e.g. the envelope/letter idiom  [Coplien], the Bridge and Proxy patterns  [GOF]). However, despite the fact that it is well-documented there seems to be a major flaw in its realization. Its deficiency lies in the fact that the dynamic binding mechanism is disrupted by introducing an additional level of indirection (by delegating to the 'body' object), since it is not possible to make calls to member functions which are refined by subclasses of the (visible) handle class in the implementation of the (hidden) body class. We restored the working of the normal virtual function mechanism by introducing the notion of explicit invocation context. In this way, the handle/body idiom can be applied completely transparently, even for programmers of subclasses of the handle.

In our realization of the handle/body idiom the handle class is used both as the interface class to access functionality implemented by its body, and as a semi-abstract base class, defining the interface of the body classes which are derived from the handle. The body object is typically instantiated directly by the constructor of the handle, but this action may be deferred to the moment of first use, or may be done indirectly by using an abstract object factory  [GOF]. To be able to make calls to member functions redefined by user-defined subclasses of the handle class, the body class must make such calls via the handle class as well. See appendix A for a detailed treatment of the idiom and its improvement.

Usage

The (improved version of) the idiom is frequently used in the hush class library. The widget library is build of a stable interface hierarchy, offering several common GUI widgets classes like buttons, menus and scrollbars. The widget (handle) classes are implemented by a separate, hidden implementation hierarchy, which allows for changing the implementation of the widget library, without the need to recompile dependent applications. Additionally, the idiom helps us to ensure that the various widget implementations are used in a consistent manner (e.g. to prevent simultaneous use of Motif buttons and OpenLook scrollbars)

The nested component pattern

The nested component pattern has been introduced to support the development of compound widgets. It allows for (re)using the script and C++ interface of possibly compound widgets, by employing explicit redirection to an inner or primary component.

Problem

Inheritance is not always a suitable technique for code sharing and object composition. A familiar example is the combination of a Text object and two scrollbars into a ScrollableText object. In that case, most of the functionality of ScrollableText will be equal to that of the Text object. This problem may be dealt with by employing multiple inheritance. Using single inheritance, it may be hard to inherit this functionality directly and add extra functionality by attaching the scrollbars, especially when interface inheritance and implementation inheritance coincide.

Background

The nested component pattern is closely related to the Decorator pattern  [GOF] and InterViews notion of MonoGlyph  [Interviews]. Additionally, by using explicit delegation it provides an alternative form of code sharing than inheritance as can be found in languages supporting prototypes or exemplars such as Self  [Ungar92].

Realization

The nested component pattern is realized by applying the virtual self-reference idiom. Key to the implementation of that idiom is the virtual self() member of a component. The self() member returns a reference to the object itself (e.g. this in C++) by default, but returns the inner component if the outer object explicitly delegated its functionality by using the redirect() member. Note that chasing for self() is recursive, that is (widget) components can be nested to arbitrary depth. The self() member must be used to access the functionality that may be realized by the inner component. Note that the realization of the idiom uses inheritance primarily for interface sharing, and not for code sharing and object composition. See appendix B for a detailed code example.

Usage

The nested component pattern is employed in designing the hush widget hierarchy. Every (compound) widget can delegate part of its functionality to an inner component. It is common practice to derive a compound widget from another widget by using interface inheritance only, and to delegate functionality to an inner component by explicit redirection.

The actor pattern

The actor pattern provides a means to offer a multitude of functional modes simultaneously. For example, a single kit object gives access to multiple (embedded) script interpreters, as well as (possibly) a remote kit.

Problem

For many applications, static type hierarchies do not provide the flexibility needed to model dynamically changing roles. For example we may wish to consider a person as an actor capable of various roles during his lifetime, some of which may even coexist concurrently. The characteristic feature of the actor pattern is that it allows us to regard a particular entity as being attributed various roles or modes and that the behavior of that entity changes accordingly.

Background

Changing roles or modes can be regarded as some kind of state transition, and indeed the actor pattern (and its associated dynamic role-switching idiom) is closely related to the State pattern  [GOF]. In both cases, a single object is used to access the current role (or state) of a set of several role (or state) classes. In combination with the virtual self-reference idiom, our realization of the actor pattern allows for changing the role by installing a new actor.

Realization

The realization of the actor pattern employs the dynamic role-switching idiom, which is implemented by extending the handle class with a set of several bodies instead of only one. To enable role-switching, some kind of indexing is needed. Usually, a dictionairy or a simple array of roles will be sufficient. See appendix C for a detailed code example.

Usage

In the hush library the actor pattern is used to give access to multiple interpreters via the same interface class (i.e. the kit class). The pattern is essential in supporting the multi-paradigm nature of the DejaVu framework. In our description of the design of the Web components in section Design, we will show how dynamic role-switching is employed for using various network protocols via the same (net)client class. The actor pattern is also used to define a (single) viewer class that is capable of displaying documents of various MIME-types (including SGML, HTML, VRML).
introduction framework patterns components conclusions references appendix experience