PureMVC, LICS and Signals – A Frankenstein Framework?

What happens if you mix together PureMVC, Signals and LICS – is it for the good of the world or the ultimate evil?

On Friday we had a good technical discussion at work about the up and coming architecture for our new product. This product (which I can’t really discuss) was the reason that I started working on LICS. It is a modular Flash Platform app that must have a variable set of modules loaded up at runtime that should not care if any of the other modules are loaded, even though communication is possible between them. I personally think LICS is a very good fit, since we are already using PureMVC elsewhere in the company.

Anyway back to the argument (sorry I’ll get to the point soon). As usual I was on the weakly typed, extremely decoupled camp, and Eamonn (a co-worker) was in the strongly typed, coherent camp. His main gripe about PureMVC (and I believe many other developers’ have this view too) is that the weakly typed body of the pervasive Notification class is a bad thing. He hates all of the casting and case statements. Although this is a valid point I find the simplicity of PureMVC a bonus, and don’t mind all this ‘boilerplate’ code, because in my view you can at least see what is going on very clearly.

Eamonn then mentioned that he thought Signals was very good and had nice runtime type checking. I had heard of Signals, but didn’t know much about it. So I thought I would take a look.

The end result was that I liked Signals. I liked them so much that I thought it might be fun to try and replace the PureMVC observer/notifier code with Signals and see if we couldn’t get some some strongly typed notifications going on. The end result of my experiment is that I have created a backwards compatible version of PureMVC that uses Signals. Because it uses signals I have added the ability to send any set of typed objects as notification arguments. I also updated LICS and the shell demo to use this new system at the same time.  In the new demo, ModuleA uses the new typed signals to do its work, so instead of

                override public function listNotificationInterests():Array
		{
			return [ ModuleANotifications.POKE, ModuleANotifications.USER_UPDATED ];
		}
 
		override public function handleNotification(notification:INotification):void
		{
                        switch (notification.getName())
                        {
 
                           case ModuleANotifications.POKE:
			       var originator:String = notification.getBody() as String;
			       moduleA.textArea.text += "Poked by: "+originator+"\n";
                               break;
 
                           case ModuleANotifications.UPDATE_USER:
                               var user:UserVO = notification.getBody() as UserVO;
	                       moduleA.textArea.text+="New username: "+user.name+"\n";
			       moduleA.textArea.text+="New address: "+user.address+"\n";
			       var cfp:CurrencyFormatterProxy = facade.retrieveProxy(CurrencyFormatterProxy.NAME) as CurrencyFormatterProxy;
			       moduleA.textArea.text += "New balance: "+cfp.format(user.balance)+"\n";
                               break;
 
                        }
		}

You can write

		override public function listTypedNotificationInterests():Array
		{
			var interests:Array = [];
			interests[ModuleANotifications.USER_UPDATED] = onUserUpdated;
			interests[ModuleANotifications.POKE] = onPoked;
			return interests;
		}
 
		private function onPoked(message:String):void
		{
			moduleA.textArea.text += "Poked by: "+message+"\n";
		}
 
		private function onUserUpdated(user:UserVO):void
		{
			moduleA.textArea.text+="New username: "+user.name+"\n";
			moduleA.textArea.text+="New address: "+user.address+"\n";
			var cfp:CurrencyFormatterProxy = facade.retrieveProxy(CurrencyFormatterProxy.NAME) as CurrencyFormatterProxy;
			moduleA.textArea.text += "New balance: "+cfp.format(user.balance)+"\n";
		}

The only extra thing you have to do is inform the system that those notifications do not send Notification object, but instead send typed objects . In the current demo I do this in the constructor of the ModuleAFacade

		public function ModuleAFacade(key:String)
		{
			super(key);
			setNotificationArgumentTypes(ModuleANotifications.USER_UPDATED,UserVO);
			setNotificationArgumentTypes(ModuleANotifications.POKE,String);
			registerCoreMediator(new ModuleACoreMediator(this));
		}

The setNotificationArgumentTypes method takes a notification name and then a list of argument classes specified in exactly the same way as when you create a strongly typed Signal (in fact that is what they are used for). Then whenever a notification with that name is sent we must supply exactly the right arguments or we will get a signals runtime error explaining what type was expected and what was actually sent. I have added the sendTypedNotification method to specifically send this type of notification.

                        var user:UserVO = new UserVO("Conrad","Conrad's Address",1000000.56);
			sendTypedNotification(ModuleANotifications.USER_UPDATED,user);

This work is still very experimental and there are certain bits I am not really happy with – the naming of methods is just one example – but I thought I would share it with you an see what other people think.

I have attached the following 3 files: LICSS.fxpl LICS using Signals, PureMVC_1.0.5_Signals.fxpl – PureMVC Multicore using Signals, and  Shell.fxp – a demo that requires both of these libraries.

Let me know what you think.

LICSS.fxpl
LICSS.fxpl
LICSS.zip
Version: 1
52.4 KiB
45 Downloads
Details...
PureMVC_1.0.5_Signals.fxpl
PureMVC_1.0.5_Signals.fxpl
PureMVC_1.0.5_Signals.zip
Version: 1
36.0 KiB
57 Downloads
Details...
This entry was posted in LICS, PureMVC and tagged , , . Bookmark the permalink.

One Response to PureMVC, LICS and Signals – A Frankenstein Framework?

  1. Pingback: as3signals tutorial | Color Hook

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">