Archive for the ‘ design patterns ’ Category

Agent Oriented Software

I’ve been obsessed lately with reading about Agent Oriented Programming (AOP). I’m fascinated about the concept of making objects autonomous and capable of responding to environmental changes, rather than predefining what they will and will not do (as opposed to what they can and cannot do).

It is interesting, for me, to note that AOP and Service Oriented Architectures (SOA) started to gain momentum around the same time, and yet the interest, and advancements, in SOA quickly outdistanced those for AOP.

In my opinion, this is because the practical applications for AOP are minimal, while the concepts of SOA can quickly and easily be grasped and implemented in many business environments.

I can’t really find any white papers from someone who’s actually implemented a project with this kind of architecture, so it all seems stalled in the theoretical phase still. Of course, I can’t think of a project that I’m working where we could use this.

I still find it fascinating, though.

What Is An Agent?
Properties of Agents
Agent Oriented Software Engineering
A Taxonomy for Autonomous Agents
Jam! Agent Architecture

Cairngorm: Abstract Events Updated

Purpose

The intended purpose for the AbstractEvent class in Cairngorm was three-fold:

  1. Reduce the number of files needed to manage business events by organizing Events into domains
  2. Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event
  3. Make each domain event class as lightweight as possible

Related Posts

Abstract Commands | Abstract Delegates

Concept

To accomplish these goals, each domain event (e.g. ProjectEvent, PaymentEvent, etc.) would be polymorphic (kinda) in that there is no longer just one identifier designated with the EVENT_ID constant. In addition, I wanted to abstract as much functionality and classification as possible into a common class that each domain event would extend.
abstract_event

Lightweight, Polymorphic Event Class

Here’s an example of a domain event. It has three public identifiers – CREATE_PROJECT, LOAD_PROJECTS, DEACTIVATE_PROJECT- and has no logic other than to pass its constructor’s arguments to AbstractEvent.

ProjectEvent.as

package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class ProjectEvent extends AbstractEvent
   {
      public static const CREATE_PROJECT:String = "createProject";
      public static const LOAD_PROJECTS:String = "getProjects";
      public static const DEACTIVATE_PROJECT:String = "deactivateProject";

      public function ProjectEvent(type:String, data:Object = null, callbacks:Array=null)
      {
         super(type, data, callback);
      }
   }
}

AbstractEvent Class

The AbstractEvent class itself isn’t much more complicated at all. It simply has three public variables to hold the type of the event, an object containing key/value pairs for the data, and the reference to the callback function in the view (if specified).

AbstractEvent.as

package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class AbstractEvent extends CairngormEvent
   {
      public var callbacks:Array = null;

      public function AbstractEvent(type:String, data:Object = null, callbacks:Array=[])
      {
         super(type);

         this.data = data;
         this.callbacks = callbacks;
      }
   }
}

Example View – Projects

Here’s some snippets of code from my project view. One piece of functionality is for a user to disable a selected project from a list in an AdvancedDataGrid. When the user clicks on the “Disable Project” button, the btnDeactivateProject_Click() function fires and creates a new Project event in which the loadProjects() function is specified as the callback function.

Projects.mxml

private function btnDeactivateProject_Click(e:Event):void
{
   var thisProject:Project = gridProjects.selectedItem as Project;
   new ProjectEvent(ProjectEvent.DEACTIVATE_PROJECT,
            {project:thisProject},
            [loadProjects]).dispatch();
}

public function loadProjects():void
{
   new ProjectEvent(ProjectEvent.LOAD_PROJECTS).dispatch();
}

<mx:Button id="btnDeactivateProject"
	click="btnDeactivateProject_Click(event)"
	x="10" y="393"
	label="Deactivate Project"/>

Mapping Events to Commands

Your controller logic doesn’t change. The only difference is that you’re using one domain event, with specified identities, mapped to different Commands.

Controller.as

package business
{
   import business.commands.*;
   import business.events.*;
   import com.adobe.cairngorm.control.FrontController;

   public class Controller extends FrontController
   {
      public function Controller()
      {
         super();
         addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
         addCommand(ProjectEvent.CREATE_PROJECT, CreateProjectCommand);
         addCommand(ProjectEvent.DEACTIVATE_PROJECT, DeactivateProjectCommand);
      }
   }
}

Cairngorm: Abstract Commands Updated

Purpose

The intended purpose for the AbstractCommand class in Cairngorm is three-fold:

  1. Further implementation of a callback feature – in conjunction with the AbstractEvent – so that a view can specify other actions to perform upon the successful completion of business event
  2. Create a Responder object for the Delegate to use
  3. Make each Command class as lightweight as possible

Related Posts

Batch Commands | Abstract Events | Abstract Delegates

Concept

abstract_command

Standard, Responseful Command

Below is an example Command in my system, it extends AbstractCommand which in turn implements the ICustomCommand interface. To make the Command responseful, an array of functions is passed from the Event to the Command, which will execute them upon success (see more below). Here’s an example call:

new EmployeeEvent(EmployeeEvent.GET_DETAILS,
         {employee_id:params.empID},
         [showEmployeeDetails, updateEmployeeGraph])

To implement a very basic command, it is only required to set the delegate property to a new instance of the appropriate Delegate class, and then invoke the needed method. The AbstractCommand will automatically create a new Responder object and assign it to the delegate.

LoadProjectCommand.as

public class LoadProjectCommand extends AbstractCommand
{
   private var _model:ModelLocator = ModelLocator.getInstance();

   override public function execute():void
   {
      delegate = new ProjectDelegate();
      (delegate as ProjectDelegate).loadProject(invoker.data);
   }

   override public function commandSuccess(event:Event):void
   {
      if (event.result.success)
      {
         _model.project = (event as ResultEvent).result.data;
         notifyInvoker();
      }
   }
}
}

The invoker object is a reference to the original Event that was called, and to get it assigned as a property of the Command, I extended the FrontController class so that it is assigned before the Command is executed.

protected function executeAbstractCommand(event:AbstractEvent):void
{
   var commandRef:Class = getCommand(event.type);
   var commandToExecute:ICustomCommand = new commandRef();

   commandToExecute.invoker = event;
   commandToExecute.execute();
}

AbstractCommand Class

This class is straightforward and handles the tedious aspects of creating a Command. The notifyInvoker() method simply loops through the array of callback functions – if they exist – and runs them.

AbstractCommand.as

public class AbstractCommand
{
   private var _callbacks:Array = null;
   private var _invoker:AbstractEvent = null;
   private var _delegate:AbstractDelegate = null;

   public function AbstractCommand() { }
   public function execute():void { }
   public function commandSuccess(event:Event):void { }
   public function commandFault(event:Event):void { }

   public function set delegate(d:*):void
   {
      _delegate = d;
      _delegate.setResponder(new Responder(commandSuccess, commandFault));
   }

   public function get delegate():*
   {
      return _delegate;
   }

   public function set invoker(e:AbstractEvent):void
   {
      _invoker = e;
      if (e.callbacks != null) _callbacks = e.callbacks;
   }

   public function get invoker():AbstractEvent
   {
      return _invoker;
   }

   public function notifyInvoker(info:Object = null):void
   {
      if (_callbacks != null)
      {
         for (var i:uint = 0; i < _callbacks.length; i++)
         {
            var callback:Function = _callbacks[i];
           (info != null) ? callback.call(this, info) : callback.call(this);
         }
      }
   }
}

ICustomCommand Interface

ICustomCommand.as

package business.commands
{
   import business.events.AbstractEvent;
   import flash.events.Event;

   public interface ICustomCommand
   {
      function commandSuccess(event:Event):void;
      function commandFault(event:Event):void;
      function execute():void;
      function set invoker(event:AbstractEvent):void;
      function set delegate(delegate:*):void;
   }
}

Cairngorm Patterns: Batch Commands

Related Posts

Abstract Commands

Basic Cairngorm Commands

In the base implementation of the Cairngorm micro-architecture, events and commands are mapped on a 1-1 basis. For every invoker (event) you have to specify one command in your controller.

public function Controller()
{
   super();
   addCommand(TeammateEvent.LOAD_TEAMMATES, LoadTeammatesCommand);
   addCommand(EffortEvent.LOAD_TYPES, LoadEffortTypesCommand);
   addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
   addCommand(TeammateEvent.LOAD_TEAMMATE_ROLES, LoadTeammateRolesCommand);
   ...
}

For most cases, this is perfectly fine, but in a data-heavy model, such as the one being built for my current application, I need to initialize the application and fire off many individual events in order to load my model with base data.

// Load all teammates in the database for display in the reports tab
new TeammateEvent(TeammateEvent.LOAD_TEAMMATES).dispatch();

// Load all effort types
new EffortEvent(EffortEvent.LOAD_TYPES).dispatch();

// Load all projects
new ProjectEvent(ProjectEvent.LOAD_PROJECTS).dispatch();

// Load all roles
new TeammateEvent(TeammateEvent.LOAD_TEAMMATE_ROLES).dispatch();

...

Batch Commands

In order to avoid having to dispatch n events for n commands to be executed, I would rather map 1 event to n commands and have them fired off in sequence. Then, if I need a batch of commands to fire, I only need to dispatch one event, instead of the 4 I used in the example above.

new ApplicationEvent(ApplicationEvent.LOAD_MODEL).dispatch();

Unfortunately, Cairngorm does not allow this, so I had to extend the basic architecture. I created a addCommands() function that maps a single event to multiple commands as an array.

public class Controller extends ExtendedFrontController
{
   public function Controller()
   {
      addCommands(ApplicationEvent.LOAD_MODEL, [LoadTeammatesCommand,
                                LoadEffortTypesCommand,
                                LoadProjectsCommand,
                                LoadTeammateRolesCommand,
                                ...]);
   }
}

Extended Controller Class

Here’s the code that I’ve come up with so far. This is working fine, but there still some things I plan on implementing in the future.

ExtendedFrontController.as

public class ExtendedFrontController extends FrontController
{
   public function ExtendedFrontController()
   {
      super();
   }

   public function addCommands(commandName:String, commandRefs:Array, useWeakReference:Boolean = true):void
   {
      if(commands[ commandName ] != null)
      {
         throw new CairngormError( CairngormMessageCodes.COMMAND_ALREADY_REGISTERED, commandName );
      }

      if (commandRefs == null)
      {
         throw new Error("The commandRefs argument to addCommands() is null");
      }

      commands[commandName] = commandRefs;

      for (var priority:uint = 0; priority < commandRefs.length; priority++)
      {
         CairngormEventDispatcher.getInstance().addEventListener(commandName, executeCommands, false, priority, useWeakReference);
      }
   }

   protected function executeCommands(event:AbstractEvent):void
   {
      var commandsToInitialise:Array = getCommands(event.type);
      var commandRef:Class;

      for (var i:uint = 0; i < commandsToInitialise.length; i++)
      {
         commandRef = commandsToInitialise[i];
         var commandToExecute:ICustomCommand = new commandRef();
         commandToExecute.execute(event);
      }
   }

   protected function getCommands(commandName:String):Array
   {
      var commands:Array = commands[commandName];

      if ( commands == null )
         throw new CairngormError( CairngormMessageCodes.COMMAND_NOT_FOUND, commandName );

      return commands;
   }
}

A Better, Stronger Flex Architecture

Cairngorm++

Call me a junkie, that’s fine, but this stuff works. I’ve said many times in the past that the whole purpose of using design patterns, code frameworks, and application architectures should be to reduce the code I write (as time progresses), make an application easier to extend, and reduce the cost of turnover.

After quickly learning what the Cairngorm architecture had to offer, I noticed several gaps that needed to be filled. One of which was the inordinate amount of files that are created using the base patterns (which I alleviated with my abstract classes for Event, Command, and Delegate). Another gap is that it doesn’t have a view mediator. That’s the one feature from the PureMVC framework that I actually was a huge fan of.

Mediators

You see, PureMVC uses a Mediator pattern in order to provide a mechanism by which views could interact with the business logic, as well as with each other, while remaining ignorant of the man behind the curtain. Keeping the views decoupled from the model is good – especially with my apps – because subtle changes to the data model happen often, and while a good part of that is handled in the business logic, it often bubbles up to the UI model as well.

I am a Command, I am an Island

Another value feature that other frameworks have is that ability for a View – via a Mediator – to actually know if a Command was successful or not. Gasp! With the base Cairngorm implementation, the only way to perform an action on success of a Command was in the Command itself. Very bad, otherwise you end up with situations that call for SaveProjectAndReloadModelCommand in which you do one action and then immediately call another Command, and SaveProjectWithNoModelReloadCommand for when you don’t need to do the second Command.

A Command should be as insular as possible. It should never directly call another Command.

Responseful Commands

My way around this was to implement a function callback feature in the Event and Command abstract classes.

abstract

When an Event is dispatched from a View, the name of a local function is passed as an argument. The Command consumes this function reference and then runs it if the execution was successful.

Tested in the Field

Sure, theory is fine, but how does all this work when actually writing a Flex app? Well, I put that to the test just the other day. An app I’m working needed a significant enhancement and change. After changing the database model, I was able to crank out the business logic, and three views in Flex in which users could create new items, deactivate/activate them, and a few other doo-dads in just under 40 minutes.

Conclusion

Don’t be afraid to enhance a framework or code architecture with your own ideas. Trust yourself and your ideas because you’re smart, too.