Over the last few weeks I have been trying to improve the documentation for Dawn on its GitHub page. I am slowly making progress (hindered a little by starting a new job) but realise there are still some real weak spots. One area in particular is Dawn's use of the command pattern. I built Dawn's commands in a bit of a rush while completing the project that demonstrated the need for them, so have held back giving them too much formal documentation until I can clean them up and add a couple more key features. That said, I still find them very useful in their current state so thought I'd write this little post to give them more of an airing.
There are lots of good reasons for using commands in your applications. They are a proven solutuion for all sorts of common problems in client side development such as queueing, cacheing, batching etc. They are also very useful for performing business logic that spans multiple domains within an application, and thus belong in no one domain alone.
In actionscript there is no way for me to extend an interface and narrow the type of the argument, this for example would be impossible
What that means is that any commands I write that want to get information out of the event that triggered them are going to have to cast the argument! Type safety FAIL! I want to be able to write type safe commands that know the exact type of their arguments.
Step 2. "implement the execute method, which takes some generic object as its argument. Find a way to get hold of any objects you need, perhaps a service locator (PureMVC) or a singleton (Caringorm)" You can probably guess what I dont like about that. Commands are so valuable because they can encapsulate complex logic that involves a number of parts of an application. But commands are stateless (created each time they are executed) and tend to be created by the framework, so how can they get hold of the objects that they need to act upon? In most frameworks I have come across objects that need to be involved in commands either need to implement the singleton pattern - the enemy of testable code! Or register with a service locator, which adds new dependencies on the command to a service locator class and a random string against which the object may (fingers crossed) be registered against. I want my commands to have as few dependencies as possible, I dont want to have to rely on strings to get hold of the core actors in my system, and I certainly dont want to fall into the many traps thats singletons lay.
step 3. "define some string or event (a string type field) that triggers the command" Having created this command in framework X I now need to think about how to trigger its execution. I might have to create a new object that extends some base event to do this, or I may just have to choose a string name. I can just about deal with this step, I know that there is going to have to be something that triggers the command (I just dont think string or events are very good choices).
step 4. "configure the framework to trigger the command on the newly defined event (one-to-one mapping)" This is where the previous step starts to frustrate me. I have to TELL the framework that the object I just created is the one that will trigger the command. This will most likely look something like so
framework.registerCommand( MyThing.NAME, MyLovelyCommand );
There are a couple of things I don't like about that, firstly it depends on developer discipline (I dont have that!), meaning it's up to me to check that the value of MyThing.NAME is what it should be, the compiler won't care if all my NAME properties have the same value!! Secondly it's configuration, and configuration does not rock my boat.
There are a few things to note
Since the command system is built on top of Dawns other libraries (DI and notifications) we can just send a notification of type MakeHay to trigger the command.
and we're done.
Why make another command library?
Enough of why commands are good (we all know that), why does Dawn contain its own flavour of this oh so common pattern? In turns out providing the command pattern is not a simple as it might seem in Actionscript, at least not if you have some design principles you intend to stick to. Most of the frameworks I have come accross in actionscript provide commands in a pretty similar way, the steps are somethings like this- Create a new object that implements some ICommand interface
- implement the execute method, which takes some generic object as its argument. Find a way to get hold of any objects you need, perhaps a service locator (PureMVC) or a singleton (Caringorm)
- define some string or event (a string type field) that triggers the command
- configure the framework to trigger the command on the newly defined event (one-to-one mapping)
interface ICommand{
function execute(event:FrameworkEvent):void
}interface MyCommand extends ICommand{
function execute(event:MyFrameworkEvent):void
}how is Dawn different?
Heres an example of what a typical command might look like in Dawn (in a typical hay making application).class MakeHayCommand{
[Inject] public var barn:Barn;
[Execute] public function execute( note:MakeHay ):void{
barn.makeHay(note.howMuchHay);
}
}- there is no ICommand interface
- the argument to the execute method is specific to the business logic being executed
- the execute method has [Execute] metadata
- the barn variable has [Inject] metadata
commands.addCommand(MayHayCommand);
notificationBus.trigger(new MakeHay(numberOfBales));
One more quick win
Another nice feature we get for free by building on top of the notification system is that any command you write is mapped by type, and types can be concrete classes (like the above example) or abstract classes or even interfaces. Here is a command that will log any notification that implements IResponderclass LogRpcCommand {
[Execute] public function execute( responder:mx.rpc.IResponder ):void {
trace("making rpc call", responder);
}
}