logo

Steven Black Consulting

Contact me

Services
Consulting
Mentoring
Training

INTL Toolkit
Support
Info
INTL VFP
INTL 2.x
Price
Upgrade
Purchase

Also
Wikis
Downloads
Articles

The Hooks and Anchors Design Pattern

(Last updated April 3 2003.  I added Parsers -- Cleaning up HTML, a sample with code -- Steven Black).

By Steven Black

Introduction

This document describes an object-oriented design pattern called Hooks and Anchors. Consider this a discussion document, an idea that may evolve into a "real" design pattern. 

Hooks and anchors are an abstract object society that I first designed in 1996 and used ever since. It has served me well in numerous desktop and internet applications. 

Here's how this paper goes: we start by examining the class structure of hooks and hook subclasses. Next we'll discuss the anchor class, which is a subclass of Hook.  

That's a conceptual nuance -- why would an Anchor be a subclass of Hook?  The placement of hooks and anchors under a common hook superclass, is explained. 

Next well look at how particular design patterns are conducive to implementations involving with hooks and anchors.

Background

All object-oriented VFP frameworks can be described as skeletal structures designed for extension.  Over time, developers grow their root framework(s) into one or more applications, refining and extending (evolving) their toolset over an extended period of time. 

Similarly, all the root frameworks give you so-called hot spots, known as Hook Methods or, as Gamma and Helm call them, Template Methods. To varying degrees, the  framework(s) you use also supply a philosophy about usage and extension. Typically the suggested philosophy is: you hook the framework's hook methods to suit your implementation-specific needs.

In the Hooks and Anchors design pattern, the hook is implemented with a hook object society, which is designed at the outset to fully encapsulate work of the hook method.  The hook method, therefore, reduces to a hook operation that delegates program flow to the society of hook objects.  

In other words, at the program's critical junctures, instead of adding code to specifically named hook methods, Hook and Anchor pattern implementations use a hook class instead, which hides a society of hooks and anchors, placing code in a  polymorphically-named action methods of fine grained hook classes.

In the Hooks and Anchors design presented here, the hook class provides a ::Process() method that is called by clients.  The ::Process() method handles pre- and post-processing, calling a protected method named ::Execute() method wherein the hook's real deed is done.

Therefore, A Hooks and Anchors society is the sort of thing you call from a hot spot, usually instead of most or all the code you would normally place there.

The crux of the matter is this:  since we're talking about VFP here, the Hooks and Anchors society is, of course, natively engineered to be metadata-driven in both composition and execution.  

Class Structure

This section focuses on the morphology of the Hooks and Anchors solution framework. We develop the concept of hook chains and anchors, and how they can be simply combined in the same class hierarchy.

UML Development

Using UML notation, Figure 1 illustrates an atomic concept of object-oriented software: two separate classes with a one-way, 1:1 relationship between them. In this case, SomeClass holds a reference to SomeHook through the SomeClass.oHook member property

Figure 1. a fundamental object micro society.

Figure 2 shows a variation of the relationship in Figure 1, except now assume that two collaborating classes are descendents of a common Parent Class. This assumption may seem like a stretch. If the classes descend from a common parent, then the semantics of the relationship can easily be refactored and generalized into the parent class. If on the other hand the classes do not descend from a common parent, then we can get the same effect with code duplication. For now, lets agree to keep things simple, and descend from a common parent, if only for convenience.

Figure 2. First-pass generalization of the object micro society to a common ancestor.

Into the Parent Class of Figure 2 we can now refactor upwards, moving the details of the relationship into the parent class, which leads to the hierarchy illustrated in Figure 3. Its not obvious upon first glance, but the hierarchy in Figure 3 excels at providing components for object chains, like for example the one illustrated in Figure 4. The key to this is the self-referential relationship link on the Hook Parent Class as illustrated in Figure 3.

Figure 3. At left, all the descendants of the Hook Parent Class inherit the self-referential relationship, and this makes them easily assembled together into chains. The diagram thus reduces abstractly to the one on the right, representing a single class with self-referential semantics.

In my experience great things can happen when you sensibly use self-referential structures like those of Figure 3 to create solutions that execute objects sequentially, as illustrated in the class diagram in Figure 4, and also illustrated in the corresponding stair-shaped sequence diagram illustrated in Figure 5.

Figure 4. A chain of N objects linked together. Normally control passes from instances of Hook1 to Hook2 to Hook3, and so on, normally without any intervention from a controlling object.

Figure 5. The sequence diagram for a chain of objects exhibits a stair-shaped interaction pattern.

Implementation Qualities of Hook Chains

In this section we discuss the types of implementations that naturally lend themselves to solutions by hook chains, then well list some of the Gamma and Helm design patterns that can be created with hook chains, and finally well as list and explain some of the problems Ive encountered when implementing hook chains.

Applications of Hook Chains

According to Riel [2]. the stair shaped interaction of hook chains, as illustrated in Figure 5, is expected to be appropriate in the following situations.

Abstraction of Hook Chains into Fundamental Design Patterns

When we analyze an object chain of two or more objects, we see that it can be applied in several of the most common structural and behavioral Gamma and Helm Design Patterns, some of which are listed in Table 1.

Gamma and Helm Pattern [1]

Intent

Bridge

Decouple an abstraction from its implementation so that the two can vary independently.

Chain of Responsibility

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

Composite

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Decorator

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Strategy

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Table 1. Some Patterns implementable with "chained structures" abstractions.

Some Notable Problems with Hook Chains

Given the usefulness of chained structures for creating a variety of micro- architectures, here is are some of the problems that come with using chains. These problems typically get worse as the chain gets longer and/or more diverse:

Extending and Enhancing Hook Chains with Hook Anchors

In the previous section we show that hook chains have both good and not-so-good qualities. Can some of the not-so-good qualities be mitigated?

The complement of the stair-shaped interaction diagram of Figure 5 is the fork-shaped interaction pattern, illustrated in Figure 6. This illustrates a prototypical so-called god-object situation, where behavior is centralized in a single object that manipulates the other objects.

Figure 6. When an object has direct control over other objects, the sequence diagram of the interaction exhibits a fork-shaped interaction pattern.

Here are some of the situations that call for a god-objects fork interaction patterns:

Note as well that holding many concurrent references to external objects pretty much comes with being a god-object.

Lets extend the class hierarchy of Figure 3 and enhance it with a new class for coordination and control purposes. In Figure 7, this new god-object class is the Hook Anchor class, which could possesses, among other things:

Figure 7. Extending the class hierarchy, this time introducing Anchors, which are designed to address the problems of free-form hook chains by providing the ability to concurrently hold many hook objects as well as iterate them in custom and controlled ways.

A notable concept to grasp from Figure 7 is that Anchor classes are hooks. Since hooks can reference hooks, and hooks can be chained, all this applies to Anchors as well.

Abstraction of Hook Anchors into Fundamental Design Patterns

Table 2 below lists of the additional Gamma and Helm design patterns especially the creational ones that the Hook Anchor classes bring, to some degree, to the table.

Gamma and Helm Pattern [1]

Intent

Abstract Factory

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Builder

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Factory Method

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Iterator

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

State

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

Table 2. Additional Patterns implementable with Hook Anchor abstractions.

Interface

Here are some of the notable methods of the hook class hierarchy, and of the anchor branch of subclasses.

Property or Method

Reason

HookParent.oData

A member which stores a SCATTER NAME object of the metadata record responsible for its creation.

HookParent.oHook

A member to hold the next object in the hook chain.

HookParent::Process(x)

This is the only method the clients will call.

HookParent::PreProcess(x)

This method is called by the ::Process(x) method, and its logical return value ultimately decides if the hook applies for this call.

HookParent::PostProcess(x)

This method fires at the end of ::Process(x).

HookParent::Execute(x)

The action method of the hook, wherein the hook actually accomplishes what it is designed to do.

HookParent::SetOHook(o)

This method is used to build the hook chain. The semantics are as follows: If This.oHook is an object, then pass the passed parameter to This.oHook.SetoHook(o). Otherwise, assign the passed object (or an object implied by the passed parameter) to This.oHook. In this way, given a new object to chain, an existing chain knows how to configure itself.

HookAnchod.aHook

Array member of hook objects to anchor and iterate.

HookAnchor::load(ccc)

Loads the hooks (or hook chains) from metadata specified by the passed parameters.

HookAnchor::Process(x)

Iterates through the collection of attached hooks and hook chains, calling the Process() method of each.

HookAnchor::ExitProcessLoop(x)

Provides an escape mechanism for exiting the iteration.

HookAnchor::SetaHook(x)

Adds an object to the collection of hooks.

Upsides

Here are some advantages of Hooks and Anchors

Downsides

Here are some downsides with Hooks and Anchors as presented here.

It takes some getting used to, and its not easy to abstract all the operations of a process into logical independent hooks, and to thereafter anchor them and iterate them properly.

Its more complex than simple subclassing and filling hot-spot methods.

Plugging in a new object involves steps that are vulnerable to configuration mistakes without tool support. Using BROWSE on a VFP configuration table is only good for those who already know what they are doing.

Applications Putting it all together

This section serves as an outline of what will be discussed in the session, and quite probably be included with sample programs on the conference CD, or downloadable from my website at http://stevenblack.com.

Conclusion

This paper briefly describes the major elements of the Hooks and Anchors solution framework. Approaching problems this in this way isnt for everyone, nor is suitable for all situations. For real hot spots, where your application can be expect evolution stress, it can be just the ticket.

Bibliography

[1] Gamma, E., Helm, R., Johnson, R, and Vlissides, J. (1994), Design Patterns, Elements of Object Oriented Software, Addison Wesley, Reading, MA, ISBN 0-201-63361-2.

[2] Riel, A (1996), Object Oriented Design Heuristics, Addison Wesley, Reading, MA, ISBN 0-201-63385-X.

[3] Class Composition for Specifying Framework Design, S Demeyer, M Rieger, TD M, E Gelsema (http://www.iam.unibe.ch/~demeyer/Deme99b/paper.html)