MVP Initialization

Model-View-Presenter is a user interface design pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic.

The Model is an interface defining the data to be displayed or otherwise acted upon in the user interface.

The View is an interface that displays data (the Model) and routes user commands to the Presenter to act upon that data.

The Presenter acts upon the Model and the View. It retrieves data from repositories, persists it, manipulates it, and determines how it will be displayed in the View.

The degree of logic permitted in the View varies among different implementations.

At one extreme, the View is entirely passive, forwarding all interaction operations to the Presenter. In this formulation, when a user triggers an event method of the View, it does nothing but invoke a method of the Presenter which has no parameters and no return value. The Presenter then retrieves data from the View through methods defined by the View interface. Finally, the Presenter then operates on the Model and updates the View with the results of the operation.

Other versions of Model-View-Presenter allow some latitude with respect to which class handles a particular interaction, event, or command. This is often more suitable for web-based architectures, where the View, which executes on a client's browser, may be the best place to handle a particular interaction or command.

From a layering point of view, the Presenter class might be considered as belonging to the application layer in a multilayered architectured object-oriented system with common layers but it can also be seen as a Presenter layer of its own between the Application layer and the User Interface layer.


In order to start with our MVP implementation you have to follow these steps:

  • Define a Mapper for an existing application or component
  • Define a listener for the  FlexEvent.PREINITIALIZE in order to perform initialization of the architecture when the  SystemManager is in place
  • Define an instance of the MapperManager class in order to let them to handle the registration and removal of each UI element from the mapper
  • Define a sub class of the InstructionEvent class in order to define the base (i.e. the path in a string format) within which the Mapper can recover the Instructions

The application / component is now ready to work with the Instructions, if you need to create a communication bridge with an AMF channel you have to define a new ServiceConnector instance and handle the result and fault event properly.

The steps to follow in order to properly work with the ServiceConnector class are:

  • Get an instance of the class
  • Define the source and destination (i.e. the root packaging of the remote class to call and the default class against which the calls will be executed)
  • Provide a valid url for the remote method (i.e. " http://snippet.gnstudio.com/snippetrepobrowser/messagebroker/amf")
  • Define the kind of service (i.e. http, https, etc.)


sc = ServiceConnector.getConnector(this);

sc.defaultSource = "com.gnstudio.snippetrepobrowser";
sc.defaultDestination = "Topic"; 

sc.initializeConnector("http://snippet.gnstudio.com/snippetrepobrowser/messagebroker/amf", ServiceConnector.SERVICE_REMOTEOBJECT);


The class is now ready to perform a call against remote methods using AMF.

In order to use this class with the MVP triad we designed you can define a listener for all the ServerSideCallEvent in the main application file and store all the calls in an HasMap?.

// Define the listener for possible remote calls
addEventListener(ServerSideCallEvent.ANONYMOUS_CALL, onAnonymousCall);


All the ServerSideCallEvent instances will be handled from a single listener that is able to store the calls in the HashMap

private function onAnonymousCall(e:ServerSideCallEvent):void{
				
        var obj:AbstractService;
			
	obj = sc.makeAnonymousCall(e.fakeObject as IRemoteMethod);
			
	hash.addItem({service: obj, target: IView(e.target),  nameSpace: e.nameSpace})
		
}


The ServiceConnector will dispatch result and fault event on the same class, so trough an helper you can easily let your presenters aware of the update

private function onFault(e:RemoteObjectWrapperEvent):void{
			
	var helper:ServiceConnectorHelper = new ServiceConnectorHelper(hash, "service", mapper);
	helper.processFault(e);
			
}
		
private function onResult(e:RemoteObjectWrapperEvent):void{
			
	var helper:ServiceConnectorHelper = new ServiceConnectorHelper(hash, "service", mapper);
	helper.processResults(e);
			
}


The ServiceConnectorHelper needs to know on which HashMap instance remove the queued calls, the key you used to store them and the Mapper instance that contains the presenter to be updated.
It's a while that we are talking about the Presenter, it's the time to spend few words about this actor of the MVP architecture.

Each UI component is split between a view that handles display and a presenter that responds to user gestures modifying the status of the view accessing it only through its interface. The Model View Presented can be roughly summarized with the following image Some core points about the presenter are:

  • Is the presenter that handle user input and data manipulation
  • While it is the view’s responsibility to display model data it is the presenter that governs how the model can be manipulated and changed by the user interface
  • This is where the heart of an application's behavior resides
  • In many ways, a MVP presenter is equivalent to the application model in MVC
  • Most of the code dealing with how a user interface works is built into a presenter class

Our implementation of the presenter implies that you extend the Presenter core class of Nabiro and store a reference to the view inside of it (remember that the view interface has to extend the IView interface in order to work with our implementation); there are no special things to do if your presenter doesn't deal with any kind of external data.
When you start to play with data you can ask to your presenter to react to different kind of changes in the model.
An application that works works with data usually deal with value objects in order to manipulate them, if you want that your presenter react to any change (i.e. the onResult method is fired every time the model has been changed) you have to say in the constructor that the presenter has to listen to any change

presenter = new Login(this, PresenterChangeDetector.ANY_PROPERTY)


If your willing is that the onResult method is fired only if one of the properties of the model is changed, then you can specify the property

presenter = new Login(this, "username")


The property usually has a correspondence in the view interface.

Attachments

1.1.2-pro © 2008-2009 agile42 all rights reserved (this page was served in: 0.16000 sec.)