The art of hush programming

Instructor's Guide


intro polymorphism idioms patterns events summary, Q/A, literature
For the average user, programming in hush amounts (in general) to instantiating widgets and appropriate handler classes, or derived widget classes that define their own handler. However, advanced users and system-level programmers developing extensions are required to comply with the constraints resulting from the patterns underlying the design of hush and the application of their associated idioms in the realization of the library.

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 that extend 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.

Invocation context

The handle/body idiom is one of the most popular idioms. It underlies several other idioms and patterns (e.g. the envelope/letter idiom,  [Coplien92]; the Bridge and Proxy patterns,  [GOF94]).

Invocation context

handle/body


Problem
Inheritance breaks with handle/body
Background
Envelope/Letter, hiding implementations
Realization
Explicit invocation contact in body
Usage
sessions, events, kits, widgets, items

slide: Invocation context

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.

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.

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.

Nested components

virtual self-reference


Problem
Realizing composites with single inheritance
Background
Decorators, prototypes
Realization
Smart delegation
Usage
Composite widgets, embedded logic

slide: Nested components

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.

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

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() method. 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.

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.

Actor pattern

dynamic role switching


Problem
Static type hierarchies may be too limited
Background
State transitions, self-reference
Realization
Dynamic instantiation and delegation
Usage
Web viewer, kit -- embedded logic

slide: Actor pattern

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.

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 treated in  [GOF94]. 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.

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 dictionary or a simple array of roles will be sufficient.

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 Web, 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).