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