« Flint Particle System version 1.0.1 released | Improving Cairngorm’s ModelLocator Part 2 - Hiding the singleton »

Improving Cairngorm’s ModelLocator Part 1 - The problem

14th April 2008

Neil Webb recently wrote about the problems with singletons in Cairngorm, and in particular the ModelLocator. In fact, there’s been a lot of criticism of Cairngorm’s over-dependence on singletons - sometimes, when working with Cairngorm it seems that everywhere you turn there’s a singleton waiting to bite you.

Well, I started looking into Cairngorm last week for a client’s project. It’s all part of a move to Actionscript 3 at their place, and the project needs to be done ASAP (don’t they always) so using a framework rather than building our own seems like a good start point. Anyway, you may know how I dislike singletons, so Neil’s post came at a very opportune moment.

The first interesting thing about the Cairngorm’s ModelLocator is that it’s not tied into the framework in any way. The IModelLocator interface is empty, and the ModelLocator is not referenced from any code within the framework. All of which means we don’t have to use a singleton. We don’t even have to use a ModelLocator. It just so happens that the Cairngorm docs and all of the examples I’ve seen indicate that one should use a ModelLocator and it should be a singleton. But that’s just one opinion repeated by lots of people. Neil’s started looking for better alternatives and I’m all for that.

The next thing to note is, since Cairngorm doesn’t care about the ModelLocator, we can choose to split it into multiple classes, breaking our model into simpler constituent parts.

Beyond this, in looking to improve the ModelLocator I have one feature I’d like to keep - the idea of binding to data within the view. More specifically, the idea that the view could potentially be built by less experienced developers dragging components into an MXML document and binding them to the model data. This is perfect for my client’s project.

So, my first idea was to use a Monostate. By which I don’t mean a class with lots of public static variables but a true monostate, where common data is in private static variables and is accessed via public methods or getter/setters. So, a ModelLocator containing a single property would look something like this

package model
{
  [Bindable]
  public class ModelLocator
  {
    private static var _username:String;
    public function get username():String
    {
      return ModelLocator._username;
    }
    public function set username( value:String ):void
    {
      ModelLocator._username = value;
    }
  }
}

That is a lot more code than a simple public variable, but it lets us define an interface (the getters and setters) and extend the class to add more features. The idea is that we can create as many instances of the ModelLocator as we like and all will be accessing the same data.

Unfortunately, it doesn’t work. The binding fails. Probably because we’re binding to different instances of the getters and setters. Which leads me to think of another solution. One that doesn’t involve removing the singleton, just hiding it.

We start with a normal singleton class to hold the model data.

package model
{
  [Bindable]
  public class Model
  {
    private static var _instance:Model;

    public static function getInstance() : Model
    {
      if (_instance == null)
      {
        _instance = new Model();
      }
      return _instance;
    }
		
    public function Model()
    {
      if ( _instance != null )
      {
        throw new Error( "The model class is a singleton." );
      }
    }
		
    public var username:String;
  }
}

Then we add a class that is used to access this singleton, with properties bound to the singleton.

package model
{
  import mx.binding.utils.BindingUtils;

  [Bindable]
  public class ModelLocator
  {
    private var _model:Model;
		
    public var username:String;

    public function ModelLocator()
    {
      _model = Model.getInstance();
      BindingUtils.bindProperty(this,"username",_model,"username");
      BindingUtils.bindProperty(_model,"username",this,"username");
    }
  }
}

Now we can create as many instances as we like of this new ModelLocator class and bind to its properties, and all will be well. So, Actionscript code can contain, for example

var model:ModelLocator = new ModelLocator();
model.username = "fred";

and equally, mxml code could contain

<model:ModelLocator id="model" xmlns:model="model.*"/>
<mx:TextInput text="{model.username}"/>

We could also make the properties into getters and setters so we can define a proper interface.

However, we are creating a lot of code. If we were to use getter/setters in the ModelLocator class there would be even more code (and more opportunity for things to go wrong). On top of that, all the bindings result in yet more code under the hood. Is there a better way?

See also:

Read more articles about Flex, Actionscript 3 

5 Comments add your own

  • Nice!

    Nicholas  |  14th April 2008 at 5:00 pm

  • Actually your first idea (to use a Monostate) was the right approach.

    If you add a bindable event to your getter:

    [Bindable(event="propertyChange")]

    and dispatch this event when the property in your setter changes:

    dispatchEvent (new Event ("propertyChange"));

    your bindings will work as expected.

    I wrote up a few more details and added some sample code here:

    http://userflex.wordpress.com/2008/04/14/bindable-getters-and-setters/

    I hope that helps!

    Nick Schneble  |  15th April 2008 at 6:12 am

  • Using Cairngorm, I already create several distinct Models to keep certain separation of data. Am I missing something here?

    This is a very interesting subject and any further investigation is always welcome.

    glen williams
    tinylion development uk
    www.flex-ria.com

    Glenn Williams  |  15th April 2008 at 9:23 am

  • @Nick

    I hadn’t picked up on the problem with binding to getter/setters in general. However, your code doesn’t fix the main problem - the bindings only exist within the instances of the class, they don’t operate across the different instances.

    @glen

    The idea here is to remove the dependency on the Models being singletons while retaining the ease of updating and binding to the data wherever required.

    richard  |  15th April 2008 at 11:23 am

  • […] Because of all those reasons, some frameworks have been created in Flex world to provide MVC pattern implementation. One such frameworks is Cairngorm which is an architectural framework to provide the separation between different MVC layers using some of the very well known design patterns from JEE world. So it may sound quite familiar to you if I talk about Front Controller, Business Delegate, Service Locator, GOF Command Pattern and Value Object patterns. Flex world still calls Data Transfer Object (DTO) pattern as Value Object because of some reasons. Along with all mentioned patterns it uses one more design pattern which is specific to Flex world and is called Model Locator design pattern. This pattern is based on singleton pattern though. […]

    Current Architectural Frameworks Developments in Flex | Xebia Blog  |  8th November 2008 at 9:35 pm

Leave a Comment

required

required, hidden

XHTML: you can use these tags - <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Subscribe to the comments via RSS Feed