Link to Gordian's home page The Black Sea of Technology
Link to New TechnologyLink to White Papers


White Papers - Articles

"Creating Synergistic Components with Delphi"

James Callan - KOG Webzine (Page 5)

Disembodied Button Pushers
Suppose that you wanted to design a component that silently recorded user actions for playback at a later time. This is not so fantastic after all. Many sophisticated commercial products include some form of macro definition and playback. To simplify our example, assume that the new component would be used for recording button and checkbox clicks only. Thus, only button clicks and checkbox clicks would be recorded in macros. Once recorded, the macro could be played back, and the application would act as if a ghost were pushing the buttons. Suppose further that the various Windows macro-recording API calls and form event processing hooks that advanced Windows programmers would use do not exist in our ghostly realm. What is another way of creating such a component?

Figure 2 illustrates a simplified class design in Booch notation for handling TButton user actions. (See the reference to Grady Booch at the endnotes for more information on his notation.) As shown, TMacroButton is inherited from TButton and contains a macro stored in a string (aggregate "by value" association) and a boolean property (also "by value") indicating whether or not the macro is being recorded or played back. The TMacroButton would, when recording, record the TButton's Click events until recording was turned "off." When playback was turned "on," TMacroButton would generate the TButton's OnClick events for each "click" present in the recorded macro.

In similar fashion, macro recorders could be built for checkboxes, radio buttons and other controls. The components could be extended to make use of a global macro string so that all the individual macro strings could be weaved onto a single macro string. Properly exposing the OnClick events to application developers using this approach would require that the component designer create a descendant class hierarchy based on all of the controls that could be used to record macros. In most cases building whole new inheritance hierarchies is neither practical, nor desirable. No, this approach would take us back to aggregation and not forward towards links and a single component solution.

A better solution approach would involve a single component, that when dropped on the form would provide the macro recording and playback capabilities, yet would also permit all the buttons on the form to retain their original design and run-time behavior. But remember, One click per customer is the rule. That's the rub. Only the button knows when it gets clicked. How does the button inform the macro recorder component? How would the button even know about the existence of the macro recorder?

The macro recorder could override the button's OnClick event, but then the OnClick event is no longer available to the application designer. The button and macro recorder must be able to collaborate, yet retain their individual strengths. They must establish a synergistic relationship.

If these issues sound scarcely similar to challenges you are now facing or that you have faced in the past, they should. Many OOP design dilemmas when approached with traditional thinking create unwieldy class hierarchies or unworkable designs. By dynamically overriding event handlers you can break through the aggregate mindset and create synergistic components. Let's consider a link-based way to build the macro recorder.

Previous PageNext Page

Signature Block of Gordian Solutions