There was a presentation a while ago talking about the different frameworks in Flex. The presenters speak ill of Cairngorm's use of Singletons (It's about 20 minutes in, but I strongly recommend watching the whole thing if you haven't seen it yet). I thought it would be a worthy discussion to discuss the complaints with Singletons, how they relate to Cairngorm, and how I deal with this when building Cairngorm applications.
What is a Singleton
Singleton is a design pattern. It is a class that is only instantiated once. Only a single instance of the singleton object will exist. The most common use of singleton that I've seen is as a location for global data. Sometimes Singletons are used in frameworks as a single point of entry into the framework APIs.
In the ColdFusion world, the application or session scope might be considered a singleton. In Cairngorm, the ModelLocator is a singleton. Using the Cairngorm paradigm, most components refer to the ModelLocator for global application data, figuring out what the state of the application is. I really like the way that the Cairngorm ModelLocator can be used in conjunction with ViewStacks and binding to display screens to the user.
Problems with Singletons
So, a Singleton is a class that is a global data store. Why is this bad? In no particular order:
- In most Cairngorm applications I've seen, all components are referencing the ModelLocator. That means these components are not portable to other projects because they are specifically tied to the application. You are creating dependencies and there is no loose coupling.
- If the components you're building are not stand alone, then it becomes complicated, if not impossible, to perform unit tests on the component. This can lead to more time in development.
- Flex, or more appropriately, ActionScript 3, does not have private constructors. As such workarounds are used to prevent multiple instances of the class from being created. In the grand scheme of thing, this is a minor issue.
- Unless you write code to "Destroy" / get rid of the stuff you are storing in the ModelLocator, it will hang out there for as long as your application is in use. In some cases this is fine. In others it can be wasteful. Loading and storing too much data could lead to memory issues.
How can I code avoid singleton problems in Cairngorm?
So, how can you write Cairngorm applications in such a way that they avoid the problems associated with singletons? Well, in reality, you can't. but, you can try to organize your application to minimize the use of the ModelLocator; which is what I Try to do:
- Top Level Application: The Top level application is my main.mxml file; the one with the Application (or WindowedApplication in AIR) root. I think it's a pretty safe bet that this will be tightly coupled with the application, and reuse on this will be rare. I'm completely fine with that. As such, it's perfectly fine for my main.mxml to reference the ModelLocator. The Main.mxml often contains a ViewStack of the Application screens, but not much else.
- Second Tier Components: The second tier components are the main screen containers. I'll generally have one of these components for each 'viewstack' index in the main application. I figure it is okay if these are tied tightly to the application, and therefore they can access the ModelLocator.
- Everything Else: The second tier components will be made up of plenty of other components (Most likely using composition). Any level below the second tier, I try to make as loosely coupled as possible. Instead to referencing global data in the ModelLocator, I'll exchange data using parameters and events. In an ideal world, I'd only have 3 layers of components, but realistically these can trickle down much further just 3 layers.
I've found that implementing this use of the ModelLocator has given me a good balance of using "Global Variables" with loosely coupled components.
I wasn't ever planning on adding another entry into my Cairngorm series, but this has been stewing in my idea pool for a while, and tonight I felt inspired. While you're reading this, don't forget about the upcoming DotComIt focus group. Flex Developer's of all levels are welcome to attend.