In this section a brief overview will be given of the basic
concepts underlying hush.
Then we will discuss the idioms used in realizing hush and
its extensions, in particular an adapted version of
the handle/body idiom originally introduced in
The hush framework is object-oriented in that it allows for a component-wise approach to developing applications. Yet, in addition to object class interfaces, it offers the opportunity to employ a script language, such as Tcl and Prolog, to develop applications and prototypes. The hush framework is a multi-paradigm framework, not only by supporting a multi-lingual approach, but also by providing support for distributed client/server solutions in a transparent (read CORBA) manner.
In this section we will look at the idioms employed for the realization of the framework. In developing hush we observed that there is a tension between defining a clean object model and providing the flexibility needed to support a multiparadigm approach. We resolved this tension by choosing to differentiate between the object model (that is class interfaces) offered to the average user of the framework and the object model offered to advanced users and system-level developers.
In this approach, idioms play a central role.
We achieved the desired flexibility by
systematically employing a limited number of basic idioms.
We succeeded in hiding these idioms from the average
user of the framework.
However, the simplicity of our original object model
is only apparent.
Advanced or system-level developers who intend to define
extensions to the framework must be well aware
of the patterns underlying the basic concepts,
that is the functionality requirements of the classes involved,
and the idioms employed in realizing these requirements.
The hush framework -- basic concepts
In developing hush, we decided from the start to support a multiparadigm approach to software development and consequently we had to define the mutual interaction between the various language paradigms, as for example the interaction between C++ and a scripting language, such as Tcl. Current scripting languages, including Python and Tcl, provide facilities for being embedded in C and C++, but extending these languages with functionality defined in C or C++ and employing the language from within C/C++ is rather cumbersome. The hush library offers a uniform interface to a number of script languages and, in addition, it offers a variety of widgets and multimedia extensions, which are accessible through any of the script interpreters as well as the C++ interface. These concepts are embodied in (pseudo) abstract classes that are realized by employing idioms extending the handle/body idiom, as explained later on.
void eval(string cmd);
string result();
void bind(string name, handler h);
};
int dispatch( event e ); to dispatch events
int operator();
};
The use of handler objects is closely connected to the paradigm of event-driven computation. An event, conceptually speaking, is an entity that is characterized by two significant moments, the moment of its creation and the moment of its activation, its occurrence. Naturally, an event may be activated multiple times and even record a history of its activation, but the basic principle underlying the use of events is that all the information that is needed is stored at creation time and, subsequently, activation may proceed blindly. See section reactor.
...
void bind( handler h );
void bind( string action, handler h );
...
};
In addition to the widget class, the hush library also provides the class item, representing graphical items. Graphical items, however, are to be placed within a canvas widget, and may be tagged to allow for the groupwise manipulation of a collection of items, as for example moving them in response to dragging the mouse pointer.
operator();
};
In order to illustrate the idiom, we use the following class as a running example:
public A() { }
public void f1() { System.out.println("A.f1"); f2(); }
public void f2() { System.out.println("A.f2"); }
};
public A() { body = new BodyOfA(this); }
protected A(int x) { }
public void f1() { body.f1(); }
public void f2() { body.f2(); }
public void f3() { System.out.println("A.f3"); }
private A body;
};
public BodyOfA() { super(911); }
public void f1() { System.out.println("A.f1"); f2(); }
public void f2() { System.out.println("A.f2"); }
};
But the major drawback of the handle/body idiom occurs when deriving a subclass of A which partially redefines A's virtual member functions. Consider this definition of a derived class C:
public void f2() { System.out.println("C.f2"); }
};
public BodyOfA(A h) { super(911); handle = h; }
public void f1() { System.out.println("A.f1"); handle.f2(); }
public void f2() { System.out.println("A.f2"); }
A handle; // reference to invocation context
};
Note that this solution does require some programming discipline: all (implicit) references to the body object should be changed into a reference to the invocation context. Fortunately, this discipline is only required in the body classes of the implementation hierarchy.
public item(String x) { _name = x; _self = null; }
String name() { return exists()?self().name():_name; }
public void redirect(item x) { _self = x; }
boolean exists() { return _self != null; }
public item self() { return exists()?_self.self():this; }
item _self;
String _name;
};
indeed, b
}
};
Those well-versed in design patterns will recognize the Decorator
patterns (as applied in the Interviews MonoGlyph class,
Taking our view of a person as an actor
as a starting point,
we need first to establish the repertoire of possible behavior.
Next, we may wish to refine the behavior of an actor
for certain roles, such as for example the student
and employer roles, which are among the many roles
a person can play.
Assuming or `becoming' a role results in creating
a role instance if none exists and setting the _role
instance variable to that particular role.
When a person's identity has been changed,
assuming a role affects the actor that
replaced the person's original identity.
(However, only a person can change roles!)
The ability to become an actor allows us to model
the various phases of a person's lifetime
by different classes, as illustrated by
the adult class.
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.
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 is closely
related to the Decorator pattern treated in
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.
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
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).
(C) Æliens
04/09/2009
Dynamic role-switching
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
dynamic role switching idiom underlying the
actor pattern is that it
allows us to regard a particular entity from multiple
perspectives
and to see that the behavior of that entity changes accordingly.
We will look at a possible realization of the idiom below.
public static final int Person = 0;
public static final int Student = 1;
public static final int Employer = 2;
public static final int Final = 3;
public void walk() { if (exists()) self().walk(); }
public void talk() { if (exists()) self().talk(); }
public void think() { if (exists()) self().think(); }
public void act() { if (exists()) self().act(); }
public boolean exists() { return false; }
public actor self() { return this; }
public void become(actor A) { }
public void become(int R) { }
};
public void talk() { System.out.println("OOP"); }
public void think() { System.out.println("Z"); }
};
public void talk() { System.out.println("money"); }
public void act() { System.out.println("business"); }
};
public person() {
role = new actor[ Final+1 ];
for( int i = Person; i <= Final; i++ ) role[i]=this;
become(Person);
}
public boolean exists() { return role
public void talk() { System.out.println("interesting"); }
};
public static void main(String[] args) {
person p = new person(); p.talk(); // empty
p.become(actor.Student); p.talk(); // OOP
p.become(actor.Employer); p.talk(); // money
p.become(new adult()); p.talk(); // interesting
p.become(actor.Student); p.talk(); // OOP
p.become(p); p.talk(); // old role: employer
p.become(actor.Person); p.talk(); // initial state
}
};
The art of hush programming
\label{hush-patterns}
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.
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, Invocation context
The nested component pattern
Nested components
The actor pattern
Actor pattern