PureMVC demo application

PureMVC is probably one of the oldest ActionScript and Flex frameworks. It was born using ActionScript, but quickly was ported to other languages like Ruby, Python, C++, PHP or Java. His name expose clearly his matrix: it follows Model-View-Controller pattern, one of the most naturally when working with Flash and Flex.

You can download the demo application from here

PureMVC have 3 core singleton clases or actors: Model, View and Controller, plus another singleton, the Façade, that simplifies development by providing a single interface for communication with the Core actors.

Is important to note that PureMVC has his own Notification system that don’t rely on Flash Events system, and is based on a model/subscriber mechanism without the need of strong typing, since it carries and object ready to be used and aditionally a string identifier, anyway nothing prevents you to use Event mechanism and in fact we use in our example.

Model and proxies

 

The Model simply caches named references to Proxies. Proxy code manipulates the data model, communicating with remote services if need be to persist or retrieve it. This results in portable Model tier code. Generally speaking, the Proxy pattern is used to provide a placeholder for an object in order to control access to it. In a PureMVC-based application, the Proxy class is used specifically to manage a portion of the application’s data model. Data manipulation is done using Value Object, basically a class with a collection of public properties. Proxies can also retrieve data from Webservices of databases in asynchronous patterns. Here’s an excerpt of our QuizProxy that gets data from an XML file:

public class QuizProxy extends Proxy implements IProxy {
    public static const NAME:String = "QuizProxy"; (...)
    public function QuizProxy() {
    super(NAME);
    var ldr:URLLoader = new URLLoader();
    ldr.dataFormat = URLLoaderDataFormat.TEXT;
    ldr.addEventListener(Event.COMPLETE, onLoadXML);
    ldr.load(new URLRequest("com/flashdb/quiz/model/questions.xml"));
}

In the constructor, we load all the quiz question that will be used trough the application an will be accessed by the view.
The proxy, as any other piece in PureMVC, is registered to the Facade (in the StartupCommand in our application):

facade.registerProxy( new QuizProxy());

The proxy never manipulates Mediators, it just send notifications. The Model maintains its integrity through the use of Proxies, which house Domain Logic, and expose an API for manipulation of Data Objects

Controller and Commands

Commands are executed by the Controller as a result of Notifications being sent. Commands should never be instantiated and executed by any other actor than the Controller. To interact with the system, commands send notifications to be responded by others commands or mediators and manipulate directly proxies and mediators. Commands house the Business Logic of our application. Commands interact with Mediators and Proxies, but should be insulated from boundary implementations.
Commands could be chained, so you can use a MacroCommand (a chain of commands) in your application. A typical example is the StartupCommand:

public class StartupCommand extends MacroCommand {
    // Initialize the MacroCommand by adding its subcommands.
    override protected function initializeMacroCommand() : void {
        addSubCommand( ModelPrepCommand );
        addSubCommand( ViewPrepCommand );
    }
} 

The StartupCommand calls two other commands when Model and View should be setup before entering the application. In our example the StartupCommand just register the proxies and the Application and Login mediators (since the others view are created by deferred instantiation)

View and Mediators

A Mediator class is used to mediate the user’s interaction with one or more of the application’s View Components (such as Flex DataGrids or Flash MovieClips) and the rest of the PureMVC application.
To the PureMVC-based application, a View Component is any UI component, regardless of what framework it is provided by or how many sub-components it may contain. A View Component should encapsulate as much of its own state and operation as possible, exposing a simple API of events, methods and properties. The responsibilities for the Mediator are primarily handling Events dispatched from the View Component and relevant Notifications sent from the rest of the system.

The base mediator accepts an argument in the constructor that represents the concrete view component. You need to explicitly cast this object based on your concrete implementation, and for this implicit getter/setter comes in handy. Another important concern of Mediators is to register a list of interests, that’s the notifications the mediator is interest in handling, and of course the handler for it. Here’s is an example of the ApplicationMediator from our example:

public function ApplicationMediator( viewComponent:Object ) {
    super( NAME, viewComponent );
}  
//implicit getter to avoid casting
private function get application():QuizPureMVC {
    return viewComponent as QuizPureMVC;
}
 (...)
override public function listNotificationInterests():Array{
    return [ ApplicationFacade.AUTHENTICATED_SUCCESS, ApplicationFacade.SEND_ANSWER, ApplicationFacade.SHOW_RESULTS ];
}
override public function handleNotification( note:INotification ):void{
    switch ( note.getName() ){
        case ApplicationFacade.AUTHENTICATED_SUCCESS:
            application.currentState = "quizz";
            break;
        case ApplicationFacade.SEND_ANSWER:
            userModel.addResult(note.getBody() as QuizEvent);
            break;  
        case ApplicationFacade.SHOW_RESULTS:
            application.currentState = "results";
     }
}

Facade

The Facade brokers your requests to the Model, View and Controller, so that your code does not need import those classes and you do not need to work with them individually. The Façade class automatically instantiates the Core MVC Singletons in its constructor.

The Façade provides an implementation that should be considered abstract, in that you never instantiate it directly. Instead, you subclass the framework Façade and add or override some of its methods to make it useful in your application. Once the application’s View hierarchy has been built, the PureMVC apparatus is started and the Model and View regions are prepared for use.

Highligths

- Since PureMVC was writed as language agnostic, his first implementation was ActionScript, so still the main documents (like best practices) features ActionScript examples, so is easy to read for Flex developers

- Since examples on StartupCommands usually calls a couple of composite commands (ModelPrepComand and ViewPrepComand), we don’t need such a preparation, but probably medium to big applications do.

- It’s very important to give views an implicit getter for the reference to the view, this way you access to the advantages of strong typing instead of work with a generic object. Also you avoid to possible receive compile errors or warnings.

- Proxies are usually paired with Value Objects to store pieces of data.

- Asynchronous access to external services is routed trough proxies, since in our case is just an XML file

- Is very important to take into account instantiation process: you can’t register a Mediator on a view not on DisplayList (say hide inside a ViewStack or TabNavigator) For this you should use Deferred Instantiation, a common problem that arise when trying to use Mediators. Take a look at ApplicationMediator in our example, it receives notifications for creationComplete callbacks upon components and register the proper Mediator as needed.

- Since proxies are useful, the lack of an exposed Model singleton that stores itself reference to data (as in others frameworks) makes confuse at beginning the use of proxies

- The ApplicationFacade, ApplicationMediator and StartupCommand are central pieces to chain the whole framework

- Using Events and Notifications is sometimes confuse, since both could be used for similar purposes. In our example application we use both.

For further reading you can check http://www.puremvc.org

About Jorge Solis

Flash-db director
This entry was posted in Flex. Bookmark the permalink.

One Response to PureMVC demo application

  1. Cliff Hall says:

    Hi Jorge,

    Thanks for putting out this demo.

    One suggestion, though. Move the URLLoader code out of the QuizProxy constructor and into onRegister(). The reason is you want your actors to be fully registered before they do anything that could result in a ‘conversation’ taking place (e.g. a mediator being interested in an outbound note and wanting to retrieve the proxy that sent the note).

    In your case you may not be sending out a note, but the general habit should be to do pretty much everything in onRegister() rather than the constructor to avoid any possibility of timing issues.

    public class QuizProxy extends Proxy implements IProxy {
    public static const NAME:String = “QuizProxy”; (…)
    public function QuizProxy() {
    super(NAME);
    }

    override public function onRegister():void
    {
    var ldr:URLLoader = new URLLoader();
    ldr.dataFormat = URLLoaderDataFormat.TEXT;
    ldr.addEventListener(Event.COMPLETE, onLoadXML);
    ldr.load(new URLRequest(“com/flashdb/quiz/model/questions.xml”));
    }

    Cheers,
    -=Cliff>

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>