The primary focal point for aMVC is the anaonymous controller. this class is in fact the motivator for the creation of the aMVC architecture. The basic underlying motivation was a centralized point of control for messaging that was not dependent on global constants, or a priori knowledge of events or functional commands.
This is one of the major drawbacks of architectures like Cairngorm (other than class overload). In Cairngorm, the FrontController class is a central mechanism in  the application that links events to responders (Commands). In a shared production environment, this requires an integration step in development work to capture all communication in a central place. In the original formulation there was also a conflict introduced by using Modular development, where there was conflict between the central application controller, and those built to support Module functionality. This conflict was resolved, thanks to work by groups such as Universal Mind, by allowing the application controller to register the FrontControllers of individual modules

In the aMVC formulation, the Controller class acts as a message gateway. Events, defined as constants elsewhere in application, are registered with the controller anonymously via the use of a Dictionary. As part of this registration (via the EventRegistrationDTO), a responder is passed and assigned via the Dictionary to this event. This initial registration and that of other interested parties are captured in the same Dictionary entry. When an event of this type is dispatched, all interested parties are notified of the event via the registered responder.

The controller neither knows nor cares who is doing the registration, who dispatched the event (is is dispatched directly on the controller, which is a Singleton), or who will handle (or initiate) actions that correspond to this event.  As outlined in the function relationship diagram, a typical flow would have a Command instance registering interest with the Controller for an event that is dispatched by a view component that responds to user interaction. This is not the only scenario e.g. view registers response handler from an event dispatch elsewhere in the application.

The framework relies on a single event Class the DataTransportEvent that can be utilized to pass any data or none. These classes are outlined here:

Controller.as

/*
 * Controller.as
 *
 * Copyleft(c) 2010 Darin Kohles.  All Rights Reserved.
 *                        www.dkohles.com
 *
 * Date: April 10, 2010
 * Author: darin@dkohles.com
 *
 */
package com.dkohles.core.control
{
import com.dkohles.core.base.SingletonBase;
import com.dkohles.core.events.DataTransportEvent;
import com.dkohles.core.events.EventRegistrationDTO;

import flash.utils.Dictionary;

import mx.rpc.IResponder;

public class Controller extends SingletonBase
{
private var responseDirectory:Dictionary;
private var eventDirectory:Dictionary;

protected var svc:M3RemoteServices;
protected var model:M3Model;

public function M3Controller()
{
super();
}

/**
* Add a responder to an event type. Used by module classes to register interest in
* external events.
* @param reg pass through object containing event type information and the responder for the event.
*
*/
public function registerHandler( reg:EventRegistrationDTO ):void
{
if( eventDirectory == null ){
eventDirectory = new Dictionary();
}

if( eventDirectory[ reg.eventName ] == null ){
eventDirectory[ reg.eventName ] = true;
addEventListener( reg.eventName, handleEvent );
}

if( responseDirectory == null ){
responseDirectory = new Dictionary();
}

if( responseDirectory[ reg.eventName ] == null ){
responseDirectory[ reg.eventName ] = new Array();
}

( responseDirectory[ reg.eventName ] as Array).push( reg.responder );
}

/**
* Remove notification interest by responder. Used to decouple component from external
* events that had been previously been tracked. Also clean up the controller dictionary
* if no other parties are interested.
*
* @param reg pass through object containing event type information and the responder for the event.
*
*/
public function deRegisterHandler( reg:EventRegistrationDTO ):void
{
var index:int = (responseDirectory[ reg.eventName ] as Array).indexOf( reg.responder );
if(index >=0 ) (responseDirectory[ reg.eventName ] as Array).splice( index, 1 );

if( (responseDirectory[ reg.eventName ] as Array).length == 0)
{
responseDirectory[ reg.eventName ] = null;
this.removeEventListener( reg.eventName, handleEvent );
}
}

/**
* Pass the event directly to the responder(s) directly.
*
* @param evt event fired by normal application flow or user gesture
*
*/
private function handleEvent( evt:DataTransportEvent ):void
{
var respArray:Array = responseDirectory[ evt.type ];
if( respArray != null && respArray.length > 0 ){
for(var i:int = 0 ; i < respArray.length ; i++ ){
if( (respArray[i] as IResponder).result != null ){
(respArray[i] as IResponder).result( evt.data );
}
}
}
}

/**
* Retrieve responders for a given event.
*
* @param evt event type of interest.
*
*/
private function getResponders( type:String ):Array
{
var respArray:Array;
if( eventDirectory[ type ] ){
respArray = responseDirectory[ type ];
}
}
}
}

EventRegistrationDTO.as

/*
* EventRegistrationDTO.as
*
* Copyleft(c) 2010 Darin Kohles.  All Rights Reserved.
*                        www.dkohles.com
 *
* Date: April 10, 2010
* Author: darin@dkohles.com
*
*/
package com.dkohles.core.events
{
import mx.rpc.IResponder;
import mx.rpc.Responder;

public class EventRegistrationDTO
{
public var responder:Responder;
public var eventName:String;

public function EventRegistrationDTO( evt:String, resp:Responder )
{
this.eventName = evt;
this.responder = resp;
}

}
}

DataTransportEvent.as

/*
* DataTransportEvent.as
*
* Copyleft(c) 2010 Darin Kohles.  All Rights Reserved.
*                        www.dkohles.com
 *
* Date: April 10, 2010
* Author: darin@dkohles.com
*
*/
package com.dkohles.core.events
{
import flash.events.Event;

public class DataTransportEvent extends Event
{
public var data:*;

public function DataTransportEvent(type:String, data:*, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);

this.data = data;
}

}
}

SingletonBase is the fundamental underlying class for the Anonymous MVC framework. All of the major support components of the framework extending this class. In this implementation, a single instance is spawned that parents all sub-class children. By adopting this approach items such as the Controller can register without conflict with co-existing Controllers from other parts of the application when used in Modular development. This allows applications to be sub-divided and developed independently without fear of naming conflict as singletons are recorded by fully qualified Class. This leaves centralization of functionality as an option to the development and not a requirement.

/*
 * SingletonBase.as
 *
 * Copyleft(c) 2010 Darin Kohles.  All Rights Reserved.
 *                        www.dkohles.com
 *
 * Date: April 10, 2010
 * Author: www.dkohles.com
 *
 */
package com.dkohles.core.base
{
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	/**
	 * Base class implementation of Singleton pattern. Single static storage for
	 * extending Class instances are stored via Dictionary.
	 *
	 */
	public class SingletonBase extends EventDispatcher
	{
		private static var instanceDict:Dictionary = new Dictionary();

		/**
		 * Public constructor. Never called directly, only through a reference call to super()
		 * from an extending sub class.
		 *
		 */
		public function SingletonBase()
		{
			var className:String = getQualifiedClassName( this );
			var clss:Class = getDefinitionByName( className ) as Class;

			if( clss == SingletonBase ){
				throw("SingletonBase is a base class that cannot be instantiated");
			}

			var instance:Object = instanceDict[clss];
			if( instance != null ){
				throw("Classes extending SingletonBase can only be instantiated once by the getInstance method");
			}else{
				instanceDict[clss] = this;
			}
		}

		public static function getInstance( clss:Class ):Object
		{
			var instance:Object = instanceDict[clss];

			if( instance == null ){
				// create a new instance of the given class
				instance = Object( new clss() );

				var singleton:SingletonBase = instance as SingletonBase;
				if( singleton == null ){
					throw("getInstance can only be called for Classes extending SingletonBase");
				}
			}

			return instance;
		}
	}
}

Please notice that the singleton base extends EventDispatcher. This allows instances to act as event capture points, which will be further illustrated in future posts.

The motivation behind the Anonymous MVC Framework (aMVC), was to separate the aspects of frameworks like Cairngorm and Pure MVC that simplify and empower application development, while avoiding the pitfalls of “centralization” that come with these implementations. The “Anonymous” portion of this framework is the use of a centralized control mechanism that simply acts as a traffic monitor for user and application initiated events.

The basic concept here is that “players” will register their interest in various events via the central controller. “Players” can be individual view components, or more commonly a command class representing a portion of the view (or it’s entirety). Part of the registration process is the pass-through of a callback function. It is in this callback that the actual activity triggered by the event is done. The callback can act within the command class, via a delegate, or directly within a view.

The framework advocates the use of a central application model (singleton), but does not preclude multiple models representing distinct portions of the application. This same holds true of all aspects of the framework, as each portion, instantiated as a singleton, is based on the qualified class. If you want to use the centralized version, call the base class, if you want to divide responsibility, simple extend the base for local use (as in Modules etc..).  The overall structure is as follows:

Framework Overview

Because of the anonymous nature of this framework, the components can be wired together with many variations:

In future posts I will elucidate further the components of this framework.

Anonymous MVC

October 15

Since I haven’t blown the dust off my blog in some time (cough). I thought I’d finally put out access to and a description of a framework I’ve been working on. The basic motivation was implementation of a basic messaging framework that is simpler and more loosely coupled than Cairngorm. The result utilizes Singletons as the basis for Command, Control and Service (as well as Model if desired) nodes that act without specific knowledge of the View components that will utilize their functionality. By decoupling this functionality, development work on projects with broad scope, and many developers can proceed very easily. Each individual contributors work can be instantly integrated.

I hope this teaser will have you checking back soon, as I will start with the basics, including code. This framework can easily be scaled from small projects to large, which I will explain in future posts.