Using Cairngorm & Thoughts On Handling Those Pesky Singletons
One assumption people tend to make about me is that because I post/speak about Cairngorm, I advocate it as being the best of the frameworks, and that's simply not true. However there are good reasons why I (currently) concentrate on Cairngorm:
- it has a low barrier to entry
- it comes from the Adobe camp
- I have more experience with Cairngorm than with other architectural frameworks
Before I talk about the Singletons I want to briefly expand upon two of those points. First of all it is comparatively easy for Flex developers to pick up and run with Cairngorm, even if they have no prior experience of design patterns. Bill Lane (GeekGlue) compares Cairngorm to the popular PureMVC framework in order to make a similar point here. We already have a situation where many Flex developers don't even know what an architectural framework is, so it makes some sense to introduce the easiest option, and from there they can make their own decisions.
Cairngorm is also worthy of consideration because it is an Adobe product. Before you jump down my throat, no, that doesn't mean it's somehow instantly better than the alternatives, but like it or not many companies will choose to go with Cairngorm for this exact reason. Doug McCune brought this up at a recent SILVAFUG meeting, pointing out that if you’re a contractor working on other people’s projects and going from client to client, the only framework you must know is Cairngorm. This may change over time, but right now it's a pretty compelling argument to familiarise yourself with Cairngorm.
The Problem With Singletons
The main reason people tell me they dislike Cairngorm is due to its over-reliance on the Singleton design pattern, and I understand.
Singletons increase coupling between classes and make them difficult to unit test. Any class which retrieves a singleton instance becomes unnecessarily coupled to the fact that the class is a singleton - it treats it in a different manor from other classes (i.e. it uses an uncommon instantiation technique). Singletons can't be substituted without changing the source of the class which uses it, nor can they be swapped-out for an interface, because singleton instances are retrieved/instantiated with a call to a static method ( getInstance() by convention ) and you can't have a static method on an interface. This limits polymorphism, going against the OO maxim "Program to an interface, not an implementation". Furthermore there is the issue of misplaced responsibility, as classes should not be responsible for limiting their own instantiation; that should be the responsibility of a factory or builder object.
So, on one hand Cairngorm makes for a good choice, and on the other, Singletons throw a real spanner in the works. Is it possible to have the best of both worlds? Well, no, but maybe we can improve things slightly...
Handling Singletons Outside of Cairngorm
Coupling can be reduced across multiple classes if we address the instantiation aspect of singletons as suggested here. To illustrate this, let's look at a couple of simple code examples which are not necessarily specific to the a framework. The first is akin to using a singleton as a global object (i.e. bad):
-
//EXAMPLE 1
-
public class A
-
{
-
public function setValue(val:int):void
-
{
-
MyModel.getInstance().value = val;
-
}
-
}
In the above example class A knows about the class MyModel and knows it's a singleton. We can't swap the singleton class for a subclass without changing code in class A.
In the next example the class is not dealing with a singleton per-se, but a type:
-
//EXAMPLE 2
-
public class A
-
{
-
private var _model:MyModel;
-
public function set model(m:MyModel):void
-
{
-
_model = m;
-
}
-
-
public function get model():MyModel
-
{
-
return _model;
-
}
-
-
public function setValue(val:int):void
-
{
-
model.value = val;
-
}
-
}
The difference here is that class A doesn't know or care whether MyModel is a singleton or not. In fact, if you needed to, you could swap it out for an interface of the same name and you wouldn't need to make any changes to class A because class A just deals with a type.
The general idea behind this is that your core class ( for example Application.mxml ) will instantiate the singleton once, and then pass that instance around to all classes which require it.
Issues: You still have global access to the singleton class of course, whether you use it or not, and that means that even if you only instantiate it once, you run the risk of other developers accessing the singleton using getinstance() from wherever they feel like doing ... but it is at least a step in the right direction.
Handling Singletons Inside of Cairngorm?
Okay, the above solution looks good, but thinking about Cairngorm specifically, where are you most likely to want access to singletons? Concentrating on just the ModelLocator, one place you'll need an instance of that is inside your commands. Here's the code for a typical command:
-
public class LoginCommand implements Command
-
{
-
public function execute(event:CairngormEvent)
-
{
-
ModelLocator.getInstance().isLoginPending = true;
-
}
-
}
The framework itself handles the actual calling of the commands for you, so, if you want to pass around an instance of the model to all commands, my initial thought would be to create a public property (or setter) on your application's controller class so that you can pass in the reference to the model, and also override the executeCommand() method of your controller instance. Here's the kind of thing I am thinking of...
-
//In your Application.mxml
-
<control:LoginController id="controller" model={ModelLocator.getInstance()}/>
-
-
//In your controller class (which is a subclass of Cairngorm's FrontController)
-
protected override function executeCommand (event:CairngormEvent):void
-
{
-
event.model = model; //store model reference within the event
-
super.executeCommand(event);
-
}
-
-
//In your command(s)
-
public function execute(event:CairngormEvent):void
-
{
-
var model = event.model;//here you have access to the reference
-
}
Whether it would be better to simply add the model reference to the CairngormEvent, or just send in the model reference as an additional parameter to the command's execute() method I'm not sure.
I'm saying "could" and "thinking of" is because currently I'm one of those bad developers who knows he should unit test, but doesn't yet ... so I don't have clearest overview of what would work best (sure I have excuses like having inherited an existing project and not having prior experience, but I know I should find the time to just do it). Anyway as a result of not unit testing, the main issues about singletons don't affect me as much ... but I'm getting ready, trying to identify the problems and thinking about how to tackle them in advance, and I'd love your feedback on this, especially if you do unit test with Cairngorm and have encountered the problems I've been describing.
Finally, here are some links which I found to be useful:
http://www.bigroom.co.uk/blog/better-without-singletons
http://blog.iconara.net/2007/05/08/on-the-good-use-of-the-singleton-design-pattern/
http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx
10 comments
10 Comments so far
Leave a reply
I think Cairngorm is over complicated.
Cairngorm makes you construct your application in a way that is not helpful or necessary.
I don’t believe it compliments the existing Flex Framework.
I don’t understand why we need any singletons.
To test these theories I’ve created my own Cairngorm-esque framework that doesn’t use any singletons..
So far it seems to be working fine although admittedly I’ve only been using it for a week now.
/**
Hi Bjorn, thanks for the reply. I certainly agree with you about the singletons. The gist of the post is intended to be “if you (have to) use Cairngorm, how do you best deal with the singletons aspect?” I don’t yet have the breadth of knowledge to agree/disagree with you about the complexity. I found it to be a great entry-level framework for teaching people, and it seems less complicated than some other frameworks I’ve looked at.
Bearing in mind that many Flex developers are self taught, an important point to make is that I’ve seen Cairngorm help people structure their applications far better than they were doing without it. Creating your own framework is great if you have that level of expertise. If it goes well I hope we’ll see your framework released as a singleton-free alternative? :)
- Neil
**/
[...] I think that there already is quite a lot of criticism of the framework in the Flex community, and I think that the guys behind asserttrue.com really did a good job in their overview of Flex frameworks. Although not critical Jeff Houser has written about the problems of singletons in Cairngorm and Niel Webb explains the same problem and proposes a solution as well. [...]
I totally agree with Bjorn’s comment. Cairngorm is just nice for people diving into Flex from a Java MVC world. When you’ve started to learn Flex you realize that Cairngorm is just an intrusion that you really don’t need and it does not provide any real value.
I have written a bit about this on my blog:
http://www.totalworldannihilation.org/blog/2008/04/11/cairngorm-a-tired-old-horse-that-should-be-put-down/
/**
Hi Leftie, just to correct one point in your article, Cairngorm is open source. As the docs explain, the reason for the two different versions is that LiveCycle Data Services has a dependency on fds.swc (which is not shipped with the standard Flex Framework) so dependencies were externalised to Cairngorm Enterprise.
I’ve started to look at presentation patterns recently, and from what I’ve read the Presentation Model looks to be a good choice. It still has its roots in the MVC pattern.
One of the patterns you would opt to keep is the ModelLocator, yet it is one of the first things I’d change ;] I’m not sure what I’m missing, but to me ModelLocator appears to be a singleton that you bind to (what *am* I missing??).
I don’t want to get too far off the topic of the article which is, “if you are using Cairngorm, how best to deal with the singletons”. There are times when people need to use it and don’t have any choice (e.g. contractors working on existing projects for a couple of months at a time).
I appreciate the comments and the link.
**/
I’m of the opinion the only useful singleton is the serviceLocator.
I disagree with the purpose of the ModelLocator.
I believe the mxml structure of your application should be considered as the model (currently in cairngorm its considered as the view).
This is my main conceptual disagreement with cairngorm.
The view should simply being focused on styling and skinning.
I don’t see why you should seperate your entire Model structure from your application, when really your model should be your application structure.
It makes things so much simpler.
I almost got a few examples to show.
Improving Cairngorm’s ModelLocator…
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 …
[...] I am terribly sorry about the mistake of not remembering that Cairngorm is Open Source. Since I wrote this I have been notified about some other articles dealing with the same issue and I think the best one yet is an article called Using Cairngorm & Thoughts On Handling Those Pesky Singletons [...]
I have moved away from Cairngorm for several reasons, some of which have already been mentioned. While I think that the use of an architectural framework (including Cairngorm) is useful for many reasons, I have to disagree with your statement that Cairngorm has a low barrier to entry.
I may misunderstand what you mean by that, but for a framework that claims to be based more on “best practices” there is an awful lot of code that comes along with it. Framework classes that need to be extended left and right; overuse of singletons; and the ViewLocator/ViewHelper abomination. This coupled with very poor official documentation make the barrier to entry pretty thick.
The code and use of the framework may be free, which is great if you’re hiring someone who already knows Cairngorm. If you have to pay someone to learn it on the job, it can tax all but the deepest pockets.
Hi John, yes perhaps I should have phrased that as being a low barrier compared to some other frameworks. I thought Bill Lane from GeekGlue summed up such a situation pretty well here, when comparing it to PureMVC
http://geekglue.blogspot.com/2007/10/cairngorm-vs-puremvc-quick-comparison.html
I guess it also differs from person to person. I found that I got to grips with the basics inside of a day or two days using a simple example as a starting block. Much of my initial framework code was copy & paste (in fact it still is), rather than getting to the point where I could have told you which classes extended which class/interface with my eyes closed. The essential part was that I got a decent overview within a short time.
Official documentation is indeed poor given that most of it deals with deprecated methods, but there is help out there. I wrote a series of tutorials for beginners (starting with http://nwebb.co.uk/blog/?p=58) and there are also other useful resources such as http://cairngormdocs.org/
I agree, paying for someone to learn any framework on the job is going to be taxing on the pockets to some degree, though it may well prove to be a wise investment in the long-term.
[...] it in to every view. Some people may suggest that we should use the Singleton pattern here (see this post for a related discussion). Whether you do or not, it is still considered best practise to [...]
[...] April 14th, 2008 | Author: dehash Using Cairngorm & Thoughts On Handling Those Pesky Singletons Tags » Trackback: Trackback-URL | Comments Feed: RSS 2.0Category: [...]