Fusioncube

The online journey of a technophile, by Steve Brownlee

Archive for March, 2009

Essential Music: Albums You Need To Own

  • Filed under: errata
Monday
Mar 23,2009

This topic made the rounds amongst my friends and family, so I thought I’d share with the remaining few people on the Internets who actually read my blog what my essential list is.

  1. ZZTop : Tres Hombres – If you want a lesson in the blues – Texas style – this one will take you for a ride
  2. Stevie Wonder : Songs In The Key Of Life – Don’t really need to say much on this one. If you don’t know it, you’ve been living under a rock
  3. Alan Parson’s Project : Tales of Mystery and Imagination – In my mind, a triumphant effort to translate the works on Poe into the musical medium
  4. Journey : Captured – Yeah, it’s pop, but it’s also Journey. ‘Nuff said.
  5. Fleetwood Mac : Rumours – Lindsey Buckingham at his greatest
  6. Michael Jackson : Triller – Easy to hate him now, but this album was a hit machine
  7. The Jimi Hendrix Experience : Are You Experienced – I can’t even imagine what Jimi would have contributed if he’d endured
  8. Led Zeppelin : Physical Graffiti – I know, I know… everyone likes the namesake better, but this was always my favorite
  9. Eagles : Hotel California – Well.. it’s Hotel California, c’mon!
  10. Guns N Roses : Appetite For Destruction – In the Hair band Hell that was the 80′s, this was a breath of hard rockin’ hell that was needed.
  11. Allman Brothers : At Fillmore East – IMHO, best live album ever
  12. AC/DC : Back In Black – Pure, unadulterated rock
  13. Pink Floyd : The Wall – Y’know… I don’t love it as much as I used to, but it’s still a must-have
Wednesday
Mar 18,2009

Purpose

My intended purpose for the AbstractCommand class in Cairngorm was two-fold:

  1. Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event
  2. Make each Command class as lightweight as possible

Related Posts

Batch Commands | Abstract Events | Abstract Delegates

Concept

Abstract Command and Interface

Standard, Responseful Command

Here’s an example Command in my system, it extends AbstractCommand and implements the ICustomCommand interface – which simply enforces a commandSuccess() and commandFault() method be present.

When the execute() method is invoked, the callback function property of the domain event is assigned by calling the setCallbackFunction() of the AbstractCommand, then the standard process of instantiating the proper delegate happens.

Now that the Command has a reference to the callback function (if it exists), in the commandSuccess() method, we simply call the AbstractCommand’s notifyCaller() method which executes that function.

DeactivateProjectCommand.as

package business.commands
{
   public class DeactivateProjectCommand extends AbstractCommand implements ICustomCommand
   {
      private var _model:ModelLocator = ModelLocator.getInstance();

      public function execute(event:CairngormEvent):void
      {
         setCallbackFunction((event as ProjectEvent).callbackFunction);

         var delegate:ProjectDelegate = new ProjectDelegate();
         delegate.setResponder(new Responder(commandSuccess, commandFault));
         delegate.deactivate((event as ProjectEvent).eventData);
      }

      public function commandSuccess(event:ResultEvent):void
      {
         if (event.result.success)
         {
            notifyCaller(event.result.data.project as Project);
         }
      }

      public function commandFault(event:FaultEvent):void { }
   }
}

AbstractCommand Class

This class is straightforward and simple. It simply contains the setCallbackFunction() and notifyCaller() methods with a private class member _callback.

AbstractCommand.as

package business.commands
{
   public class AbstractCommand
   {
      private var _callback:Function = null;

      public function setCallbackFunction(value:Function):void
      {
         if (value != null) _callback = value;
      }

      public function notifyCaller(info:Object = null):void
      {
         if (_callback != null)
         {
            if (info != null)
            {
               _callback.call(this, info);
            } else {
               _callback.call(this);
            }
         }
      }
   }
}

ICustomCommand Interface

This interface simply enforces the implementation of the commandSuccess() and commandFault() methods.

ICustomCommand.as

package business.commands
{
   import com.adobe.cairngorm.commands.ICommand;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;

   public interface ICustomCommand extends ICommand
   {
      function commandSuccess(event:ResultEvent):void;
      function commandFault(event:FaultEvent):void;
   }
}

Cairngorm Patterns: Abstract Events

Wednesday
Mar 18,2009

Purpose

My 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 my 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, callback:Function = 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 eventType:String = "";
      public var eventData:Object = new Object();
      public var callbackFunction:Function = null;

      public function AbstractEvent(type:String, data:Object = null, callback:Function = null)
      {
         super(type);
         eventType = type;
         eventData = data;
         callbackFunction = callback;
      }
   }
}

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 p:Project = gridProjects.selectedItem as Project;
   var event:ProjectEvent = new ProjectEvent(
                                  ProjectEvent.DEACTIVATE_PROJECT,
                                  {project:p},
                                  loadProjects);
   event.dispatch();
}

public function loadProjects():void
{
   var projectEvent:ProjectEvent = new ProjectEvent(ProjectEvent.LOAD_PROJECTS);
   projectEvent.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 difference 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);
      }
   }
}
Thursday
Mar 12,2009

Purpose

My intended purpose for the AbstractDelegate class in Cairngorm was two-fold:

  1. Reduce the number of files needed to manage business events by organizing Delegates into domains
  2. Make each domain Delegate class as lightweight as possible

Related Posts

Abstract Commands | Abstract Events

Concept

Abstract Delegate

Lightweight Delegate

By extending the AbstractDelegate class, each domain Delegate created by a developer become absurdly lightweight and simple. Basically, it become a series of methods mapped to remote procedure call names.

ProjectDelegate.as

package business.delegates
{
   public class ProjectDelegate extends AbstractDelegate
   {
      public function loadProjects():void
      {
         send("getProjects", {});
      }

      public function deactivate(eventData:Object):void
      {
         send("deactivateProject", eventData);
      }

      public function createProject(eventData:Object):void
      {
         send("createProject", eventData);
      }
   }
}

AbstractDelegate Class

The the AbstractDelete class will take care of holding the reference to the application’s data model, and constructing the final RPC with the designated Responder attached.

AbstractDelegate.as

package business.delegates
{
   import business.RemoteFactoryLocator;
   import flash.utils.getQualifiedClassName;
   import mx.rpc.IResponder;

   public class AbstractDelegate
   {
      private var _responder:IResponder;
      private var _remoteService:RemoteFactoryLocator = RemoteFactoryLocator.getInstance();

      public function AbstractDelegate()
      {
         if(flash.utils.getQualifiedClassName(this) == "business.delegates::AbstractDelegate")
         {
            throw new Error("ClassInstantiationException: Cannot create an instance of an abstract class.");
         }
      }

      public function setResponder(responder:IResponder):void
      {
         _responder = responder;
      }

      public function send(eventName:String, eventData:Object):void
      {
         _remoteService.send(eventName, eventData, _responder);
      }
   }
}

So now all of my delegates extend the AbstractDelegate which allows us to write less code for all of these stinking delegates for our application.

The only ramification is that the Commands (see Abstract Command post for example) now have to call the setResponder() method on each delegate.

Flex Growing Pains

Monday
Mar 2,2009

As we continue to transition from HTML/Javascript user interfaces to Flex ones here at work, we continue to go through the expecting growing pains when learning any new technology. From the simple (“How on earth do I specify a custom tooltip? oh…), to the complex (“If we provide the ability to move this control within the panel, how do we get the other controls to adjust themselves accordingly? oh….”), we’ve had many AHA! moments in the past few months.

Luckily, we are all very seasoned application developers, and there have only been a few problems to which we’ve been unable to apply past experiences and overcome quickly. Our expertise is growing quickly, and I can see in my head a year from now, after we’ve all built our collective intellectual base of knowledge of Actionscript and MXML, what amazing things we’ll be able to accomplish as we move beyond the mundane tasks of figuring out the intricacies of a ViewState, to being able to conceptualize the application as a whole and how it fits into the business needs.

It’s been amazing to see the difference at how quickly a new technology can be learned and implemented when working with a team of developers who are advanced and experienced , as opposed to a smart, talented novice.

It’s that vast accumulation of failures and successes and stored design patterns and workarounds that we all build during our careers that can significantly reduce the cost of a technology transition. I remember reading an article not long ago from someone espousing that experience – while definitely a factor – is not one of the major factors when looking to hire new developers. I’ve always disagreed with that. Someone with 10 or more years experience is likely able to learn technology faster, see hurdles ahead and how to avoid them, and generally see the big picture better than a greenhorn.

So the growing pains continue, but they hurt less and less each day.

About Steve

I am a technologist, and have been ever since 1980 when I got my very first TRS-80 and programmed it to do my math homework. I love to share the gift of technology with others and show them the wonderful things it can do for them, and how they should not fear it, but embrace it.

Latest Tweets

  • 56 Light & Clean Website Designs Using A Minimalist Color Scheme | SpyreStudios http://t.co/vbUBSJC2
  • Ok... stayed up way too late trying out website designs for my wife's new nonprofit. The kids will be getting me u... — http://t.co/QrKh5iBI
  • Am I the only one who likes Google’s new privacy policy? http://t.co/qwcym5wH
  • All that time wasted learning the .NET framework - Fusioncube - http://t.co/krANoWmg
  • @marcesher libraries like Less only do what you tell them. You can make a mixin to do that, but it doesn't assume anything (which is good)

Subscribe

Entries (RSS)
Comments (RSS)