Execute Around Method and Proxy Goulash - by Alan Griffiths

A recent design discussion resulted in a solution that has elements with strong similarities to the "Execute Around Method" and "Proxy" patterns while, in both cases moving outside the scope of the usual descriptions of these patterns [Henney2001, GOF1995].

This article discusses the scenario we encountered; notes the similarities and differences to the canonical forms of "Execute Around Method" and "Proxy" patterns; and, raises the question "are these still the same patterns - or have they been cooked beyond recognition?

Intent

To grant access to specific functionality only between paired operations.

Motivation

When updating large amounts of state it may be desirable to ensure that a "before" and "after" messages are sent to the owner of that state to ensure that any necessary preparation or cleanup may be applied - or that concurrent operations can be inhibited.

Consider a batch update of the product lines available within a system. A complete list of product lines is supplied by an external source and used to create, amend or delete product lines available within the system. Because the only indication that a product is to be deleted is that no data is supplied it is necessary to accumulate information regarding the product lines accessed during the update and to deal with deletions when the update completes.

Typically the product lines are be stored as rows within an RDBMS and accessed via a Broker class that provides the persistence mechanism. The Broker provides a finer grained and more extensive interface than is required by the needs of the application and access normally mediated by a Director that acts as a Façade [GOF1995] for this and Brokers for related objects. (In an EJB based system the Director would be a stateless session bean and a Broker used in place of an entity bean to avoid the cost of unwanted synchronisation.)

In keeping with its role as a Façade the Director should have the responsibility of calling "start" and "finish" methods on the Broker before and after processing of the batch update. However, receipt of the update is not the responsibility of the Director and, in fact, is driven another part of the system entirely. (It might be possible to wrap the processing of the input as an "iterator" passed to the director - however this would add complexity to the system.)

This leads us towards a variation of "Execute Around Method" where the paired operations are "start" and "finish" method calls (not resource allocation) and whose target is the Broker (not self invocation on the Resource object as described by Kevlin Henney [Henney2001]). We still have Kevlin's Command object - but not only has Resource been split into Director and Broker it is not passed to the Command's applyTo method ("run" in Kevlin's paper) method.

However, we've not yet resolved the full context - as the implementation of the Command interface still won't have access to the necessary Broker methods. But this is where our variation on Proxy comes into play: we define a ProxyBroker class that, being in the same package as the Broker, has access to the necessary functionality and can implement public forwarding functions. It is this (not a resource) that is passed to the Command's applyTo method.

This usage of Proxy differs from that described in [GOF1995] because additional functionality is exposed by the Proxy class. Specifically it doesn't substitute for a Broker. (I feel it is far closer to Proxy than to Adapter or Bridge.)

Participants

Broker (Broker)
- supplier of the functionality to which access is controlled by

Façade (Director)
- responsible for enforcing the access control protocol

Proxy (BrokerProxy)
- forwards calls to the Broker within the controlled scope

Consequences

The client code in UpdateCommand.applyTo () has access to the Broker.update() method via the BrokerProxy. The Director is able to ensure that start() and finish() are invoked at the appropriate points in the executeAround method.

Sample code

The following code illustrates the implementation of this dish in Java. We'll assume that a product line comprises its name and price:

Acnowledgements

Thanks to Andrew Rigley and Jason Martin who: brought the motivating example to my attention; allowed me to participate in an interesting design session that led to the above resolution; and, reviewed the draft article. Also thanks to Jason who supplied the sample code on which the above fragments are based.