RobotLegs is one of the more recents frameworks based on Dependency Injection like Parsley or Swiz, but with a strong emphasis in a Model-View-Controller arquitecture, that is suggested as the pattern of choice (but is not mandatory) RobotLegs use the SwiftSuspenders library to perform injector in the three allowable ways: constructor injection, parameter (method/setter) injection and property (field) injection.
Injection mappings are supplied to Robotlegs in three places. The MediatorMap, the CommandMap, and through the Injector directly. Both the MediatorMap and the CommandMap are making use of the Injector as well, but they are doing additional work required by these tiers. As the names imply, MediatorMap is used for mapping Mediators, CommandMap is used for mapping Commands, and anything else that needs to be injected (including but not limited to Models) is mapped directly with the Injector.
You can download the demo application from here
Context
At the heart of any Robotlegs implementation lies the Context. The Context, or Contexts as the case may be, provides the mechanism by which any given implementation’s tiers will communicate. An application is by no means limited to a single Context, but for many use cases one Context is sufficient. The Context has three functions within an application: provide initialization, provide de-initialization, and provide the central event bus for communication. In this sense is similar to the ParsleyConfig mxml file or the Swiz Beans mxml, where the main configuration is provided.
Here’s the startup method of the Context in our example:
override public function startup():void
{
// Controller
commandMap.mapEvent(LoginEvent.LOGIN_REQUESTED, AuthenticateCommand);
// Model
injector.mapSingleton(UserProxy);
injector.mapSingleton(QuizProxy);
// Services
injector.mapSingletonOf(IAuthService, DummyAuthService);
// View
mediatorMap.mapView(QuizRobotLegs, ApplicationMediator);
mediatorMap.mapView(LoginForm, LoginFormMediator);
mediatorMap.mapView(QuizView, QuizViewMediator);
mediatorMap.mapView(ResultsView, ResultsViewMediator);
// Startup complete
super.startup();
}
Controller and Commands
The Controller tier is represented by the Command class. Commands are stateless, short-lived objects used to perform a single unit of work within an application. Commands are appropriate for communication between application tiers and are able to send system events that will either launch other Commands or be received by a Mediator to perform work on a View Component in response to the event. Commands are an excellent place to encapsulate the business logic of your application.
View and Mediators
The View tier is represented by the Mediator class. Classes that extend Mediator are used to handle framework interaction with View Components. A Mediator will listen for framework events, add event listeners to the View Components, and send framework events in response to events received from the View Components they are responsible for. This allows the developer to put application specific logic on the Mediator, and avoid coupling View components to specific applications.
Probably the most important view in our example is the QuizView, that iterates over the questions listening to user selections (onRegister fires automatically when the framework instantiates and bind the Mediator):
override public function onRegister():void
{
quizView.addEventListener(QuizEvent.USER_SELECTION, onAnswer);
quizView.qModel = quizModel;
}
protected function onAnswer(evt:QuizEvent):void
{
userModel.addResult(evt);
if (quizView.qModel.hasNext())
{
quizView.qModel.moveNext(evt);
}
else
{
dispatch(new QuizEvent(QuizEvent.FINISH));
}
}
Model, Service and the Actor
Conceptually there are many similarities between the service and model tiers in the MVCS architecture. Because of this similarity, models and services are extended from the same base Actor class. A class that extends the Actor base can serve many functions within your application architecture. We are going to utilize extensions of Actor for defining both the models and the services an application will need .
Model
Model classes for use in the model tier encapsulate and provide an API for data. Models send event notifications when work has been performed on the data model. Models are generally highly portable entities. We follow the same lines as in PureMVC (probably just because do this example after the other) and use Proxies and ValueObjects for our model. In the heart of our Quiz, there’s a simple QuestionVO holding the basic neccesary needs as a collection of public properties:
public var answerA : String;
public var answerB : String;
public var answerC : String;
public var answerD : String;
public var correct:int;
public var selected:int;
public var time:String;
Service
A Service for use in the service tier communicates with “the outside world” from within an application. Web services, file access, or any action that takes place outside of the scope of your application is appropriate for a service class. Service classes dispatch system events in response to external events. A service should be highly portable, encapsulating interaction with an external service. We use a dummy AuthService to simulate the user login
Framework Events
Robotlegs uses native flash events for communication between framework actors. Custom events are typically utilized for this purpose, it is however possible to use existing Flash events for this same purpose. Robotlegs does not support Event bubbling, as it does not depend on the Flash display list as an event bus. Utilizing custom events allows developers to add properties to the Event that can be used as strongly typed payloads for system events between framework actors. In our example we use the typed LoginEvent and QuizEvent for communication
Highlights
- We have used a very similar structure as in PureMVC, but with injection avaibility, code becomes more compact, bur naming convention is very similar (Mediators i.e)
- As in Parsley and Swiss, to allow Dependency Injection variables need to be public, I have expend some time when my injection fails until find that my injected variables are private (probably you as me, use always private variables by default)
- The best practices document is a very concise guide to build the basics in good shape and short time.
- You can use normal addEventListener and dispatchEvent to normal event handling but if you want to use RobotLegs event bus, you should use eventMap.mapListener and dispatch.
- Pay attention to different methods to instantiate classes: mapValue, mapSingleton, mapSingletonOf are different ways to provide a class or an instance of a class as a singleton value
- Remember that the framework use lazy instantiation, that means instances are not created until they’re needed, so will not exist magically if you don’t inject somewhere.
- There’s an interesting example where RobotLegs use Signals isntead of normal Flash Events. Signals are light-weight, strongly-typed AS3 messaging tools writed by Robert Penner. We’re not using in our example right now, but will use in a future example so take a look at Joel Hooks bloog
Foru further reading you can check http://www.robotlegs.org/






