Warning: This is long and probably VERY boring.. unless you are an AS3 junkie, and you’re interested in so called “lightweight micro-architectural frameworks” for Flash and Flex.
A couple of weeks ago I played around with Mate and Swiz. I already knew a little about Dependency Injection (in theory anyway), but playing with those two frameworks really drove the point home: applications are potentially MUCH easier to write, and much more flexible, when you take advantage of Dependency Injection.
If you’ve used PureMVC you might be familiar with writing code like this:
var myProxy:MyProxy = facade.retrieveProxy(MyProxy.NAME) as MyProxy;
This is sometimes referred to as the Model or Service Locator pattern. Firstly, it’s a little tedious to write. But more importantly, it puts the responsibility on your class to “fetch” the things it needs – not a good thing (especially from a testing point of view). From the “outside” you can’t see what your class is dependant on: you have to review the actual code in your class to see what it wants to pull in from the outside world.
It’s also a bit sneaky: to get something out, you have to know how it was put in – splitting and spreading knowledge across your codebase. Not pleasant.
Enter Dependency Injection
Another solution is to declare certain properties on your class as dependencies to be “given” to you on (or just after) construction. A Dependency Injection framework will take care of managing these dependencies and providing you with what you need. Your class can then focus on doing it’s job instead of worrying about how to get the objects it needs.
I Like The Mediator Pattern
And I like the concepts in PureMVC: Specifically the Mediator, Command and Proxy patterns. I like clean view components with absolutely no framework or application code in them – as made possible by the Mediator pattern. I like Commands and I like binding them to system events. I like Proxies, who only communicate outwards, by dispatching events, and who’s APIs must be accessed directly by Commands and/or Mediator instances.
But I don’t like the use of Singletons or Multitons, the Service/Model locator pattern, the spreading of knowledge throughout the system by the Mediator and Proxy registration and retrieval mechanism (you have to know how something was put in to get it out again), and the custom Notification scheme and it’s associated methods: listNotificationInterests and handleNotification (with that nasty switch!).
So, I like PureMVC, I just think it could be improved for certain use cases. Now, obviously, improvement is subjective. Designing a framework is largely a balancing act: every decision has a pro and a con, and the framework architect must weigh up the pros and cons to steer the project in a chosen direction. That direction is determined by the architects vision of the most important use cases for the framework. I think that PureMVC has been brilliantly designed when stacked against it’s objectives. It’s been very carefully thought through, has an amazing author and community, sports great documentation, examples and utilities, and does it’s job well.
YALMAFRIA (Yet Another Lightweight Micro-Architecture For Rich Internet Applications)
Mate and Swiz can both do Dependency Injection. What I found interesting about the Dependency Injection in Mate is that it’s event based – this allows you to look at the event target to determine the instance that is currently being injected into. Using that (and a thing called an Object Builder in Mate) I was able to configure my application to automatically create Mediators for view components as they arrived on stage, and set references to the view components on the newly created Mediators.
It worked, but it seemed a little klunky, and still required a fair amount of code to map a Mediator Class to a view component Class (and any other dependencies). Regardless, it got me amped – using Dependency Injection and automatic Mediator registration I could remove most of the boring (and brittle) code from my projects.
I decided not to use Swiz or Mate in the end. Both offer nice solutions to some of the challenges of building RIA applications, but neither would make building my current application any quicker or easier.
Besides: I didn’t like the idea of using the display list as a system event channel, as in the case of Mate, or the concept of a central (Singleton) event dispatcher, as in the case of Swiz. And I didn’t want to put ANY application or framework code into my view components, as both seem to encourage.
Also, I wanted a framework that I could use for both Flex AND plain AS3 projects. I believe that this is possible with Swiz, but certainly not with Mate.
So, I looked for an AS3 Dependency Injection library to build a(nother) micro-architectural framework on top of..
Back to Dependency Injection
I tried Spring ActionScript (previously known as Prana) first. Immediately, two things bugged me about it: the use of external xml files to configure dependencies, and the side-effect of that requirement:
When compiling a SWF the compiler ignores Class definitions that are not directly referenced by the application. A small problem, easily solved, but an extra step none the less to ensure all necessary Classes are compiled. Loading your dependencies externally is groovy, fo sho, but I really don’t need that right now.
I believe you’d enjoy Spring ActionScript if you’re from Java land (hello there, have you played with Clojure yet? it got me all jazzed for a spell.. even though I didn’t build anything useful with it).
Anyhoo.. check this out if you are interested in Spring ActionScript and Autowiring: link
Or this, if you want to see how to do a similar thing with Swiz: link
Inspired by Guice
Next I checked out SmartyPants-IOC. I liked the vibe and proceeded to build my little framework with it.
I decided to call my framework RobotLegs. It’s very simple really. It contains two factories (and some Interfaces):
A Mediator Factory – for automatically creating and wiring up Mediators as view components arrive on Stage.
And a Command Factory – for binding commands to events.
Everything else is handled by Dependency Injection thanks to SmartyPants. Conceptually, the framework is much the same as PureMVC, but uses DI in place of a registry, and built-in Flash Events instead of Notifications.
I was able to migrate my current project over to Robot Legs (from PureMVC) in about a day. Not bad considering there were dozens of Commands, over 20 Mediators and around 10 Proxies to convert. It was a bit of a mission creating all the custom Event Classes to replace my Notifications though.
But it was certainly worth it. My application code has tidied up nicely. Many of my Mediators, Proxies and Commands have halved in size, due to the removal of lookup code and notification body casting.
The cool thing about Mediators that automatically wrap themselves around view components as they appear is that it greatly simplifies dealing with composite, lazily instantiated view components. I don’t need to worry about how a view component comes into being, I just set up a rule that ensures when that view components arrives I have a Mediator to link it back into the application. This is great for items inside Tab Navigators, Accordians, View Stacks etc.
It does present a little problem however: context. When you manually create and register a Mediator, you have the opportunity to give it some context, such as setting a property on it. Mediators that get automatically created make this a bit tricky. We could, of course, set that property on the view component, to be picked up by the Mediator on registration, but that’s not cool – view components should be self-contained, stand-alone widgets.
My current solution is to allow Mediators to request properties from parent Mediators. This is made possible by the Mediator Factory, with it’s dictionary of currently registered Mediators and view components, and a method declared by the Mediator Interface called “provideProperty”.
I plan on releasing Robot Legs once it has settled down a bit – using it in my current project has pointed out a great many things that I had overlooked initially. It won’t be everyone’s cup of tea – nothing is
UPDATE: RobotLegs 0.1, with demo Flex app, has been released. More info here: