Skip to main content
Participant
November 23, 2008
Question

Removal of Singleton Pattern from Cairngorm

  • November 23, 2008
  • 5 replies
  • 1834 views
Removal of the Singleton design pattern has many benefits for Cairngorm with regards to Unit Testing and Modules.

So far the list of Singletons used in Cairngorm are ServiceLocator, ModelLocator and CairngormEventDispacther.

I've looked into solutions to replace all Singletons with Dependency Injection.
So far here are a summary my conclusions.

The ModelLocator.
Singleton Purpose: A single point of reference for View or Commands to reference the Model.

Solution:
1, Pass the model object via the event to the command.
2, Pass the model object to the view via reference (DI).
All model instances are instantiated in a factory with all required dependencies passed via reference through the model object's constructor. The Model hierarchy represents the Display Object structure, therefore each presentation model should contain a reference to the next view's presentation model.

ServiceLocator:
Singleton Purpose: A single point of reference for Delegates to reference Services.

Solution: Similar to Prana.
Create Delegate instances in FrontController.
Have a reference of ServiceLocator within FrontController.
Set services on Delegates when Delegate gets instantiated.
Inject delegate into command.
This should remove the need for ServiceLocator to be a singleton.

CairngormEventDispatcher.
Signleton Purpose: Gives Model Objects and Commands the ability to dispatch Cairngorm Events.

Solution: Model and Commands do not talk to FrontController.
The Proposal here is that if we are using the Presentation Model pattern commands are only ever used as Responders.
Command sequencing is never initiated within a command.
Model events are routed through the view.
View events are bubbled events that are listen to by the frontController.

These are broad statements, with the intention of creating discussion rather then stating "facts".
I have created a version of the framework that uses each of these points that i'll post if need be.
This topic has been closed for replies.

5 replies

Participating Frequently
November 24, 2008
From Miko's page http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial

> The ideal solution here is to pass in the singleton as a parameter in the user's constructor, allowing a tester to easily mock out the singleton for tests.

This is what I suggested with the delegate and command constructors

> The singleton then doesn't have to enforce its own singularity; this can be handled by the client or a factory class, which could produce the real version or a test version, eliminating the global state altogether. In fact, it should be considered a violation of the Single Responsibility Principle of OO design to have an object responsible for its own singularity as well as its normal tasks.

This is what we get when we keep instance based models in the ServiceLocator or view, or pass them around in events.

> My idea was based around removing all global state practices from Cairngorm.

Well as long as you don't loose sight of it's original purpose - disciplined use of singletons can be useful for MVC, in fact I haven't come across an MVC framework that doesn't rely on at least one singleton (the application is a singleton too) to locate things.

> There is also an argument that Singletons make extending a framework difficult. This applies to the CairngormEventDispatcher.

Actually the CairngormEventDispatcher is useful for extensibility - it's a good example of the Observer pattern, letting anyone come along and plug in their own responses to events without modifying the existing framework code (although I would argue for some bits of the FrontController to be protected instead of private).

Robin
Participant
November 24, 2008
According to Miko Hevery http://misko.hevery.com/about/ Global state is the root cause of testing difficulties in 90% of cases.

My idea was based around removing all global state practices from cairngorm.

There is also an argument that Singletons make extending a framework difficult. This applies to the CairngormEventDispatcher.
Participating Frequently
November 24, 2008
Hi Bjorn,

Quick notes:

- Unit testing view code is difficult in most UI technologies.
- You can pass model references around in Events in Cairngorm if you want to, we did that extensively in some of our applications, especially those with multiple instance-based models.
- IModelLocator is just to mark your intent to use a class as a singleton model. Cairngorm doesn't say this is the _only_ way to create and reference a model. We usually only use IModelLocator for session/global type models that will always be singletons, leaving our other models to be instance based and passed around in events or looked up through the service locator. It works well for us - as always we just use the bits of Cairngorm that are useful for the problem we're facing at the time.

Cheers,
Robin
Participant
November 24, 2008
Unit testing views (as opposed to components) seems very difficult due to the nature of the MXML language and where the new operator is used.

The Presentation Model Design Pattern that Paul Williams wrote articles on seems to do a good job of separating application logic from the view that can then be isolated and tested.

It seems that the Presentation Model can be set on their corresponding views easily without the use of a ModelLocator.

The models can then be passed via the event object to the command.

That being said, what purpose remains for the ModelLocator?
Participating Frequently
November 24, 2008
Bjorn,

To support unit testing on our delegates and commands we've usually added optional arguments to command and delegate constructors, e.g.:

public function SomeDelegate( responder : IResponder, service : AbstractService = null)

and

public function SomeCommand(delegate : * = null)

We don't unit test the views but we avoid dependencies on the model in reusable view components by injecting model references into them with binding.

We don't like too many singletons around either, but haven't found the need to change Cairngorm to do this - for instance we've used the ServiceLocator as a more general purpose registry for all sorts of business singletons, and even models (which give us the option of multiple instance based models when we need them).

Cheers,
Robin