Thursday, February 18, 2010

When is a Cairngorm command not a command?

Answer: When it's a Cairngorm 3 command

Cairngorm 2, notwithstanding the architectural weaknesses it inherited from EJB2, included an implementation of a pattern that's become widely used in Flex applications; the command pattern.

In this patten a command object is used to represent a request to perform a unit of work. Typically in a Flex application command instances represent calls to the service layer on the server where each command object stores the paramenters to perform its unit of work. Since Flex's I/O framework is fully asynchronous, several requests to the same operation on the service layer may be be underway at the same time. The command pattern with a separate instance for each request provides a elegant way to manage concurrency in a Flex application. In a Cairngorm 2-based Flex application, each time you dispatch a Cairngorm event, a fresh instance of the event's corresponding command object is created by the Cairngorm framework. If the same Cairngorm event is dispatched again while the first operation is still in progress you'll end up with another instance of the same command, each one representing a specific call, each with its own specific parameters.

As a conseqeunce of this design Cairngorm 2-based applications can safely assume that each command object is specific to each request and may store state in instance variables of the command object. That’s a safe assumption since that’s how the command pattern is defined.

One of the most remarkable features of the collection of libraries that Adobe have chosen to call “Cairngorm 3” is that it doesn't provide an implementation of the command pattern. In Cairngorm 3's "integration library" (implemented as a Parsley extension), commands are now singletons that are re-used by concurrent requests. While in many cases Flex applications will ensure the serialization of requests to the same operation, in general this means that applications written for Cairngorm 2 can't be easily migrated to Cairngorm 3. Cairngorm 3 simply doesn't provide an implementation of the command pattern that's compatible with previous versions of Cairngorm. In fact it doesn’t provide an implementation of the command pattern at all. Worse still the [Command] decorator is used in Cairngorm 3 to decorate these singletons implies that these decorated classes are implementations of the command pattern when they’re not.

Parsley appears to have replicated this mistake in its most recent release (2.2) which now also supports the [Command] decorator to decorate these singletons. This decorator would have been better named [Operation] or something else that doesn’t imply that the decorated class is an implementation of the command pattern. The good news is that the latest release of Parsley does provide an implmentation of the command pattern in what it calls “short-lived commands" and “dynamic commands”. These “dynamic commands", like in Cairngorm 2, are created each time a request event is handled. Unfortunately Cairngorm 3 doesn’t currently support Parsley’s implementation of the command pattern yet so if you’re thinking of upgrading an existing Cairngorm 2 application to Cairngorm 3 I’d think twice about using Cairngorm 3 in its current state.

If you’re keen to add presentation models to an existing Cairngorm 2 application while leveraging a dependency injection framework (to get rid of all the references to Model.getInstance() etc…), then Spring ActionScript is a great choice since (ironically) it includes much better support for Cairngorm 2’s command pattern (in its optional Cairngorm 2 support library) than Cairngorm 3.

1 comment:

tom.sugden said...

Hi Graeme,

My recommendation would be to use the short-lived command objects from Parsley over the Cairngorm 3 commands. I expect the Cairngorm 3 implementation to be deprecated, since the Parsley one is superior.

The library was really a stop-gap, since Commands were already on the Parsley roadmap, but Adobe wanted an implementation sooner for some of their projects. At the time, Parsley didn't have the extensibility points for short-lived objects, so the pattern was corrupted in the way you describe. Parsley now has the necessary hooks, but there's not much point in improving the Cairngorm 3 library now they're "native" in Parsley 2.2.

I think the Short Lived Command feature of Parsley is a particularly nice implementation of this pattern. The favouring of convention over configuration minimizes boiler plater code and avoids framework dependencies in the form of interface or base class obligations. Plus it restores the elegance of the original Cairngorm commands, that you highlight, for asynchronous actions.

Best,
Tom