Skip to content
François de Campredon edited this page Jun 24, 2013 · 3 revisions

#Building MVC Architectures

Parsley is different from several other Flex or Flash MVC Frameworks in that it does not provide very much explicit support for the various pieces of an MVC architecture. This was a side effect of our primary goal being to allow to design a fully decoupled architecture. Decoupled in a sense that not only the parts of your application are decoupled from each other, but also decoupled from the framework itself. For example providing base classes for controllers or mediators in the framework that application classes have to extend is a bad idea if you want to support such a decoupled architecture.

For that reason the Messaging Framework in Parsley which we already described in Messaging is pretty generic. It does not assume a particular programming style or architectural pattern. Nevertheless Parsley still falls into the same category as many other MVC Frameworks since the Messaging Framework can easily be used in a way that helps building an application based on the MVC architectural pattern. In this chapter we will provide some examples on how to use the Messaging Framework in such a context.

##MVC Event Flow Example

The following diagram shows an example flow for a particular use case (user adds item to shopping cart) in the context of a Parsley MVC application:

Explanations for the numbered steps from the diagram:

  • 1: The user clicks the "Add to cart" button. With Flex for example this will generate a low level UI event. The event handler in the component invokes a method on the presentation model instance (usually injected into the view) which handles communication between View and Controller.

  • 2: The model creates an application message possibly gathering any further information from the view and encapsulating this information in the message. This message will then be dispatched through Parsleys MessageRouter

  • 3: The MessageRouter will then process any MessageHandlers or Commands which were registered for this message type (usually with Metadata tags on methods or properties, alternatively in MXML or XML). In this case the AddToCartCommand will be invoked.

  • 4: The command will invoke a remote service method (the service usually being injected). The asynchronous operation will be managed by the framework which allows to avoid some of the usual plumbing code. Neither the command nor any other part of the application has to explicitly add a result handler to the AsyncToken returned by the remote call.

  • 5: The framework receives the result. It is first returned to the command instance itself if it contains a result handler. But this is purely optional.

  • 6: The result handler in the command might modify or cache the model before it gets passed to other result handlers.

  • 7: Next the framework will invoke any other registered result handlers in the application. In this case the CartPM contains a result handler which will now be invoked causing the model instance to update its internal state.

  • 8: The view is refreshed, usually through binding to properties of the presentation model.

From the example above many core elements will have been setup and wired in a Parsley Context including the view as described in Dynamic View Wiring. This usually includes all controller actions, their dependencies like remote services, and the registration for particular messages in the MessageRouter.

If you think this diagram smells like over-engineering, it merely serves as an example for a full blown MVC architecture of a large and complex application. In smaller and simpler applications you can of course simplify the design presented above.

##Example Command Implementation

Finally we'll pick one of the pieces presented in the diagram above and show how the implementation and configuration of such an application part may look like. We'll chose the AddToCartCommand that participates in the application flow shown in the diagram.

package com.bookstore.actions {

import mx.rpc.AsyncToken;
import mx.rpc.Fault;
import mx.rpc.remoting.RemoteObject;

import com.bookstore.messages.AddToCartMessage;
import com.bookstore.services.CartService;
import com.bookstore.model.LineItem;

public class AddToCartCommand {


    [Inject(id="cartService")]
    public var cartService:RemoteObject;

    
    public function execute (message: AddToCartMessage): AsyncToken {
        return cartService.addItem(message.item);
    }
    
    public function result (item: LineItem): void {
        /* modify or cache the result */
    }
    
    public function error (fault: Fault): void {
        /* handle fault */
    }
    
}

} 

And this is how you can map such a command to a message in a Parsley configuration class (in this case MXML):

<parsley:MapCommand type="{AddToCartCommand}" />

We'll now examine the various parts of this class in detail. First there is the method that executes the command:

public function execute (event: AddToCartMessage) : AsyncToken {

The method parameter tells the framework that we are interested in AddToCartMessage. MessageHandler selection happens based on message type, so in a large and complex application you won't run into problems having to maintain event type constants which are unique across the whole system.

In the body of that method we are using the injected CartService:

[Inject(id="cartService")]
public var cartService:RemoteObject;

In this example we are using a RemoteObject. We usually prefer to use injection by type but this is not applicable for RemoteObjects which can only be distinguished by id. For details see Remoting.

Finally there are the result and error handlers:

public function result (item:LineItem) : void {
    
public function error (fault:Fault) : void {

We are following a naming convention here so we can avoid any metadata configuration altogether. Based on the method names the framework knows which method executes the command and which handles results or faults. The result and error handler are both optional.

Overview

Getting Started

Configuration and Initialization

Dependency Injection

Decoupled Bindings

Messaging

Managed Commands

Object Lifecycle

Dynamic View Wiring

Building Modular Applications

Building MVC Architectures

Localization

Extending the Framework

Remoting

Logging Configuration

Troubleshooting Guide

Configuration Tag Reference

Clone this wiki locally