PureMVC - Multicore vs Standard / Singlecore
I’ve recently started using the Actionscript 3.0 Multicore implementation of PureMVC in order to use the framework within a modular Flex application. At the time of writing, most of the PureMVC examples and tutorials online are relevant to the Standard, or Singlecore, version of the framework.
In general, the methodology and syntax is indentical across both versions of the framework. There are, however, a couple of minor differences which are pretty important, as without understanding these little quirks, many of the sample applications built using the Singlecore implementation will break when ported to Multicore.
The Standard version of PureMVC uses Singletons to provide access to the framework’s core actors. Within the framework, access to the Facade, Model, View and Controller are all provided using a standard getInstance method. To allow multiple instances of the framework to co-exist, the Multicore version of the framework uses Multitons, and then access to the various actors is provided within the framework by passing a unique instance key to the getInstance methods. The idea is simple - each separate instance of the framework has its own unique key, and so multiple instances of the actors may co-exist without interfering with each other.
In both versions of the framework, all instances of subclasses of Notifier (this includes Mediator, Proxy, SimpleCommand and MacroCommand) provide an easy way of accessing the facade using the protected property, facade.
The Standard implementation achieves this by creating an instance variable, defined as follows:
The Multicore implementation achieves this by providing an implicit getter, defined as follows:
{
if ( multitonKey == null ) throw Error( MULTITON_MSG );
return Facade.getInstance( multitonKey );
}
Obviously, if you are using the Multicore instance and your code tries to access the facade (for example, to register a new Proxy, or to send a Notification) before the multitonKey has been set, it will not work as expected, and an exception will be thrown. In particular, if you try and access the facade within the constructor of your Mediator or Proxy, it will fail, and you’ll see an Exception with the message “Error: multitonKey for this Notifier not yet initialized!“. How are you supposed to know when the value of the multitonKey has been set?
Digging around in the framework, it becomes clear that when a Mediator is registered with the View, or when a Proxy is registered with the Model, a couple of things happen. Firstly, Notifier’s initializeNotifier method is called, with the multitonKey passed as the only parameter. Secondly, a reference to the Proxy or Mediator is stored in the relevant proxyMap or mediatorMap. Finally, a call to the View or the Model’s onRegister is made.
As a result, it looks like there are a couple of prime candidates when it comes to deciding where to place any interactions with the facade that must occur when the Proxy or Mediator is first created. You can override the initializeNotifier method, using code similar to:
{
super.initializeNotifier (key);
// from here on, you can happily interact with the facade
// your code can be placed here
}
or you can override the onRegister method, using code similar to:
{
// from here on, you can happily interact with the facade
// your code can be placed here
}
Personally, I prefer overriding onRegister, because it involves less typing (and therefore I’m less likely to bugger something up…).
So, now when looking at one of the popular PureMVC examples, originally written for the Standard version of the framework, it’s easy to see what would need to change if porting the application to the Multicore version. As an example, the Flex Login example contains a Mediator named LoginPanelMediator. Its constructor looks like:
{
super(NAME, viewComponent);
//
// local reference to the LoginProxy
_loginProxy = facade.retrieveProxy( LoginProxy.NAME ) as LoginProxy;
//
// listen to events dispatched by its view component
loginPanel.addEventListener( LoginPanel.TRY_LOGIN, login );
}
We can see straight away that this would fail when ported to the Multicore version of the framework. During the constructor, the Mediator is trying to retrieve a proxy from the facade, but at this point the multitonKey will not have been set. We could refactor this class, resulting in a change to the constructor, and a newly created override of the onRegister function:
{
super(NAME, viewComponent);
// listen to events dispatched by its view component
loginPanel.addEventListener( LoginPanel.TRY_LOGIN, login );
// constructor no longer contains any references to the facade
}
override public function onRegister () : void
{
// when this method is called, the multitonKey has been set,
// so we can safely access the facade
// local reference to the LoginProxy
_loginProxy = facade.retrieveProxy( LoginProxy.NAME ) as LoginProxy;
}
The differences between the Multicore and Singlecore/Standard versions of the framework are really very minor, but it’s worth remembering to always move any interaction with the facade out of a Proxy or Mediator’s constructor.
August 15th, 2008 at 7:01 am
Funny. I was just going into my blog to point out that you had written a nice entry about the multicore transition when I saw your comment.
I actually learned/had my eyes opened to a solution while I was reading this entry on your blog. It’s common sense to go ahead and register the proxy as an instance variable sometimes but I had not been doing that. When I saw it at the bottom of this entry it gave me a “duh” moment.
By the way…where was this entry when my debugger was spewing red!!
August 15th, 2008 at 7:03 am
[...] Just came across an excellent entry on lowpitch.com addressing the same issue. [...]