The quest for a Dependency Injection container continues. The most recent stop on this exploration of the available options has been Robotlegs. Robotlegs AS3 is a DI driven MVCS framework for Flash/Flex inspired by PureMVC. Being a huge fan of PureMVC, this caught my attention immediately. Robotlegs professes to be a framework like PureMVC, but without all the Singeltons, Service Locators, casting and boiler plate we have all come to love. Better yet, it delivers on these claims.
Source for this demo available on github…
Brief Code Walkthrough
I’m using the same gallery example I used for Parsley, with some enhancements. The basic structure is like a typical PureMVC application. We’ve divided our packages up into model, view, controller, and events. Instead of extending Facade to bootstrap our application we need to instantiate a Context in our Applications main mxml/as file:
1 2 3 4 5 6 7 8 9 | import com.joelhooks.robotlegs.demos.imagegallery.ImageGalleryContext; import mx.events.FlexEvent; private var galleryContext:ImageGalleryContext; protected function creationCompleteHandler(event:FlexEvent):void { this.galleryContext = new ImageGalleryContext( this ); } |
The Context defines which IoC adapter to use (currently SmartyPants-IoC is the only available adapter, but a SpringAS adapter is in the works). It also fires its startup method which registers a series of commands and dispatches a Startup event.
The Context for the application defines a series of Commands to fire in sequence to get the application
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class ImageGalleryContext extends Context { public function ImageGalleryContext(contextView:DisplayObjectContainer) { super( contextView, new SmartyPantsInjector(), new SmartyPantsReflector() ); // Keep SmartyPants quiet NoSmartyPantsLogging; } override public function startup():void { // Map our startup commands commandFactory.mapCommand( ContextEvent.STARTUP, PrepModelCommand, true ); commandFactory.mapCommand( ContextEvent.STARTUP, PrepServicesCommand, true ); commandFactory.mapCommand( ContextEvent.STARTUP, PrepViewCommand, true ); commandFactory.mapCommand( ContextEvent.STARTUP, StartupCommand, true ); // And away we go! eventBroadcaster.dispatchEvent( new ContextEvent( ContextEvent.STARTUP ) ); } } |
These Commands are very similar to PureMVC commands. The Startup commands are used to define the initial injected classes and relationships between view components and their mediators.
Mediation is particularly sweet with Robotlegs. Once a view component has been associated with a mediator, it will be registered automatically:
1 | mediatorFactory.mapMediator( GalleryView, GalleryViewMediator ); |
avoiding the need for facade.registerMediator… as well as skipping around the deferred instantiation/lifecycle issues that plague Flex applications. because we are injecting into our mediators, there is no need to have the mediator ask for its dependencies. We tell it what it needs and it does its work with what it is provided:
1 2 3 4 5 6 7 8 9 10 | public class GalleryViewMediator extends Mediator { [Inject] public var galleryView:GalleryView; [Inject] public var galleryProxy:GalleryProxy; [Inject] public var imageService:IGalleryImageServiceDelegate; |
Mediating view components is hands down my favorite aspect of PureMVC, and Robotlegs enhances that pattern by removing the egregious boiler plate. It allows my view components to be completely isolated and ignorant of the surrounding framework. I don’t want to inject data directly into the components or bind them to the Model. They need to display information to and collect input from the user.
Robotlegs has eliminated the Notifications of PureMVC, using AS3 events instead. Most of the current crop of IoC containers for Actionscript do this also, but Robotlegs has avoided using the Display List as the Event Bus or requiring a central Event Map. This is huge. There are no confusing issues with bubbling, or the need to pass around a reference to THE view component.
from the GalleryViewMediator.as:
1 2 3 4 5 6 | override public function onRegisterComplete():void { addEventListenerTo( galleryView, GalleryImageEvent.SELECT_GALLERY_IMAGE, onImageSelected ) addEventListenerTo( eventDispatcher, GalleryEvent.GALLERY_LOADED, onGalleryLoaded ) this.imageService.loadGallery(); } |
The core Robotlegs classes have an eventDispatcher that is the central event management aperatus. You then dispatch events using the dispatch() method on Proxy, Mediator, and Command classes and any interested party will respond.
ANOTHER micro-architecture framework?!
Well, yes. Shaun makes several compelling arguments for pursuing another framework. I personally like options. A full toolbox. The landscape of AS3/Flex frameworks is looking mighty fine, with players to suit almost any style and approach. Instead of griping about the deficits in the available architectural frameworks, he’s made an attempt to bring the good parts of the available frameworks together while eliminating the various anti-patterns that caused him grief.
I haven’t made much of an effort to conceal the fact that I am very much a PureMVC fan boy. I like the structure, I like mediating my views as a mechanism for separation of responsibilities, and cliff Hall is one helluva guy. This isn’t to say that PureMVC doesn’t have its faults. The 4 Singletons that comprise the heart of the System, namely Facade, Model, View and Controller make for some difficult testing. The boiler plate is tedious, though at this point I just blindly type it, use a generator, or use TextExpander. None of these have been deal breakers for me, and I have worked on half a dozen large scale production projects with PureMVC. All of them have been succesful, scaled well, and were easy to manage from a development perspective.
That said, given the opportunity to eliminate the drawbacks of PureMVC, while still retaining the scalability and general workflow, I am all over it.
Sounds great, what’s the catch?
Robotlegs actively defines a PureMVC style MVC structure to your application. You are extending framework classes with your actors instead of using plain-old-actionscript objects. Other frameworks avoid this, but at the cost of convenience in a lot of cases. If you like the PureMVC structure, this isn’t going to be a big deal. If you hate it, you might hate Robotlegs (but should give it a try anyway). Robotlegs has done a great job of reducing the pain involved by addressing the major complaints that I’ve seen publicly in various critiques of PureMVC.
Robotlegs is still very young and hasn’t been thoroughly peer reviewed. My guess is that you will start to hear more about this framework soon. It is already kickass, even at this early stage. Certainly one to keep your eye on.
Resources:
Robolegs Google Group
Robolegs Screencasts
Robolegs Source
The Robotlegs AS3: A Dependency Injection Driven MVCS Framework for Flash/Flex – Inspired by PureMVC by Joel Hooks, unless otherwise expressly stated, is licensed under a Creative Commons Attribution 3.0 United States License.