Glue Code
Problem
How can Scripted Components notify the interpreter and other components when events occur?
Context
Your application is composed of loosely coupled components that have no knowledge of which other components are being used in the application. It is very common that components must notify other components when specific events occur, especially when components are used to interface with external devices or user interfaces, or to obtain data from other components in the system. For example, a button component in a user-interface toolkit must notify the application when the user has pressed the button.
Forces
- Components must interact with other components in the system.
- A component should not rely on specific components being present in the application (apart from the language interpreter).
- How a component interacts with other components in the system is application specific. Therefore it must be possible to specify how a component interacts with the rest of the system.
Solution
Use scripts - fragments of interpreted code - as Strategies to parameterise the component with application specific interactions. When the component needs to interact with other components in the system, it executes the appropriate script in the language interpreter.
Consequences
The implementation of a component is completely independent of which other components are in use by the application.
The behaviour of a component and its interactions with other components is not fixed: it can be parameterised by the script writer and can change dynamically during the execution of the script.
Components written in a low-level programming language must pay a performance penalty for this flexibility because the Glue Code must be executed by the language interpreter. If performance is paramount, it is often better to use Configuration Scripting to directly connect binary interfaces of components.
Glue Code can be used to implement the Observer pattern (however, see below for complications) and as a replacement for the Template Method pattern. This is especially useful with scripting languages such as Tcl, that do not support object-oriented features such as inheritance and abstract interfaces.
In object oriented scripting languages, the use of Glue Code reduces the need for deep class hierarchies and large numbers of classes because it reduces the motivation for using patterns such as Observer, Template Method, and FactoryMethod which typically require defining new classes or subclassing existing classes.
It is easy to use Glue Code to specify many-to-one interactions between components. That is, many components can be given scripts that perform invocations on one other component. However, it can be difficult to implement one-to-many interactions - such as the Observer pattern - when the set of components invoked must change dynamically, because that requires parsing and rebuilding the Glue Code script. In such situations, use a Broadcaster component.
Known Uses
This pattern is pervasive throughout the Tcl event handling and Tk user interface libraries. For example, Tcl channels can be supplied with scripts to evaluate when data is available for reading or required for writing and Tk widgets are configured with scripts to specify how a program reacts to user input.
Stephen Uhler's HTML parsing library for Tcl/Tk uses Glue Code to define how the HTML parser interacts with other components in a program.
ActiveX components expose event sources through which they notify clients of events. A VisualBasic script can be bound to an event source and executed when the component announces the event.
Example Code
The following example of a Tcl script shows how Glue Code is used to connect a scrollbar and a listbox so that the user can scroll the contents of the listbox by dragging the scrollbar. The scrollbar object is configured with a script which changes the current display of the listbox and the listbox is configured with a script which positions the thumb-wheel of the scrollbar to indicate the portion of the list visible in the listbox's window.
scrollbar .scroll -command {.lb yview}
listbox .lb -yscrollcommand {.scroll set}
pack .lb .scroll -side right -fill y -expand yes
.lb insert 0 A B C D E F G H I J
The following example, taken from the Tcl FAQ, shows the flexibility provided by Glue Code: a single scrollbar can be made to scroll more than one listbox by changing its glue script.
proc ScrollListboxes {listboxes args} {
foreach lb $listboxes {
eval $lb yview $args
}
}
scrollbar .scroll -command {ScrollListboxes {.lb1 .lb2 .lb3}}
listbox .lb1 -yscrollcommand {.scroll set}
listbox .lb2 -yscrollcommand {.scroll set}
listbox .lb3 -yscrollcommand {.scroll set}
pack .lb1 .lb2 .lb3 .scroll -side right -fill y -expand yes
.lb1 insert 0 1 2 3 4 5 6 7 8 9 10
.lb2 insert 0 a b c d e f g h i j
.lb3 insert 0 A B C D E F G H I J