Robotlegs AS3: A Dependency Injection Driven MVCS Framework for Flash/Flex – Inspired by PureMVC

robotlegs.org

robotlegs best practices

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…

Get Adobe Flash player

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.

Be sure to check out Shaun’s response to these items in the comments below.

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.

As of now Robotlegs has been receiving a lot of peer review and input. At the .9 release it is approaching razor sharpness

robotlegssketchsmall

Resources:
Robolegs Google Group
Robolegs Screencasts
Robolegs Source

  • http://shaun.boyblack.co.za/blog/ darscan

    Glad you're checking it out :) To briefly touch on “the catch” though:

    “Robotlegs actively defines a PureMVC style MVC structure to your application.”

    Not exclusively. The example mvcs.* implementation does, but the idea is that you can create other architectures (contexts), as long as they promise to satisfy dependencies, and then run them along side each other in one instance of the AVM (with no unintentional cross-talk). So, while the current mvcs implementation is PureMVC-style, future architectures need not be.

    “You are extending framework classes with your actors instead of using plain-old-actionscript objects.”

    Only if you want to. For the most part, the mvcs implementations just provide some oft-needed dependencies (references to the context's injector, event dispatcher etc), and some convenience methods (though I am skeptical of these): you could skip the inheritance and just add the dependencies to plain old objects by hand, as and when you need them. Well,.. that's the idea anyway – how reasonable/useful that is I'm not sure yet.

  • http://shaun.boyblack.co.za/blog/ shaun

    Glad you're checking it out :) To briefly touch on “the catch” though:

    “Robotlegs actively defines a PureMVC style MVC structure to your application.”

    Not exclusively. The example mvcs.* implementation does, but the idea is that you can create other architectures (contexts), as long as they promise to satisfy dependencies, and then run them along side each other in one instance of the AVM (with no unintentional cross-talk). So, while the current mvcs implementation is PureMVC-style, future architectures need not be.

    “You are extending framework classes with your actors instead of using plain-old-actionscript objects.”

    Only if you want to. For the most part, the mvcs implementations just provide some oft-needed dependencies (references to the context's injector, event dispatcher etc), and some convenience methods (though I am skeptical of these): you could skip the inheritance and just add the dependencies to plain old objects by hand, as and when you need them. Well,.. that's the idea anyway – how reasonable/useful that is I'm not sure yet.

  • http://joelhooks.com Joel Hooks

    Thanks for the clarification Shaun, and that makes sense. I really like the PureMVC paradigm, but it is cool to not be limited to that structure.

  • http://joelhooks.com Joel Hooks

    Thanks for the clarification Shaun, and that makes sense. I really like the PureMVC paradigm, but it is cool to not be limited to that structure.

  • http://www.jadbox.com Jonathan :: JADBOX.com

    Robotlegs seems to be exactly where I started with my library last year. That project finally evolved into FlashMVC. http://www.flashmvc.com

    It differs from Robotlegs in that there is less leg work (pun) in setting up the command roster. Commands automatically register themselves to their parents, and their Events also acts as their mediators/models. This reduces redundant code significantly.

    As a fellow framework developer, I would like to get your feedback as well.

  • Nikos

    shame so many jobs in london are still looking for pureMVC, still im gonna stick learning RL until I can find a job