MG: Flex - Better Delegates and Putting Responders in Their Place

In my first cuts of Model-Glue: Flex, I wrote a bit of helper called an Autoproxy that let you call a service from a controller, passing along a reference to Result and Fault callback functions. It was simple, familiar, and did away with manually dealing with AsyncToken and the like.

It did, however, have a bad architectural flaw: it moved knowledge of your service's response format (e.g., XML) into your controller tier. I have the same issue with Cairngorm, where the Command acts as a responder, resulting in architectural logic mingling with format massaging. Not good in either case.

Model-Glue: Flex solves this problem by encouraging you to move all knowledge of asynchronous services (RemoteObject), data services (Consumer), and whatever AIR may bring to the table into your Business Delegates.

Instead of using controller functions as responders (mixing service and control tiers), Model-Glue: Flex can use events to act as a Hub and Spoke system for dealing with external services.

Ok, real world example. Let's pretend I'm writing a Movie Collection manager, and I want to write Flex (via Flash Remoting), Flex (via LCDS), and AIR implentations. I don't want to write controller code for each: they should all share the same view and controller code as much as possible.

With Model-Glue: Flex, I could write a single delegate interface:

package business {

import model.Movie;

public interface IMovieCollectionDelegate() {
   function listMovies():void;
   function saveMovie(movie:Movie):void;   
   // etc. }

}

Then, I can implement it with RemotingMovieCollectionDelegate, ConsumerMovieCollectionDelegate, etc.

When listMovies() is executed from the MovieCollectionController, each implementation could take its own specific type of action:

  • Remoting Implentation: Ask the service locator for the service, invoke operation using Model-Glue: Flex's AsynchonousOperationHelper to assign a callback (in the Remoting delegate). When callback is called, parse out the result (XML, AS3 from CF, etc.), and dispatch a Model-Glue event (e.g., "movies.received" contains the resultant array of Movie instances .
  • Consumer: Simply dispatch a Model-Glue event containing the latest list of Movie instances.
  • AIR: Read movies from filesystem, embedded SQLLite database, merge of local and remote, etc. Then, dispatch the Model-Glue event containing the latest list of Movie instances....

What have we done?

We've moved knowledge of our external services (remoting, LCDS, filesystem, database) out of our controller and into implementations of an interface. Going further, we're using Model-Glue's Implicit Invocation layer as a Hub-and-Spoke messaging architecture, allowing the delegates (the spokes) to communicate events (receiving a new list of Movies) back to the hub (Model-Glue's front controller) via messages (Model-Glue events). Combining these (isolation of services and messaging), we've now got an application that doesn't care if it's using async, push, or AIR. Woot!

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Great stuff Joe! I love the framework!

Questions:
How can I handle the selection of particular business objects at runtime?

If my app is running offline I want my AIR delegates, but online I want my Remoting delegates. So I need a way to select the appropriate delegates at runtime.
# Posted By Jason Holden | 7/25/07 5:09 PM
Thanks Jason!

You just hit the nail on the head with the next question. I just put this up on RIAForge to help: http://fling.riaforge.com
# Posted By Joe Rinehart | 7/26/07 3:33 PM
...and followed it up with a more formal announcement:

http://www.firemoss.com/blog/index.cfm?mode=entry&...
# Posted By Joe Rinehart | 7/26/07 4:18 PM
Joe,
During the last few years, I extend the Cairngorm framework to be more scalable and support thru all layers the IResponder approach. Similar to your AutoProxy, we have a Callbacks class that implements the IResponder. In this way ANY calls can submit itself (via the Callbacks or AutoProxy) as an IResponder to commands, asynchronous services, etc.

Nice work with your Flex Model-Glue.
# Posted By Thomas Burleson | 11/14/07 7:53 AM
© 2008 Firemoss, LLC
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.