nwebb

Flex, Flash, AIR

Archive for the 'Design Patterns' Category

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):

Actionscript:
  1. //EXAMPLE 1
  2. public class A
  3. {
  4.      public function setValue(val:int):void
  5.      {
  6.          MyModel.getInstance().value = val;
  7.      }
  8. }

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:

Actionscript:
  1. //EXAMPLE 2
  2. public class A
  3. {
  4.      private var _model:MyModel;
  5.      public function set model(m:MyModel):void
  6.      {
  7.           _model = m;
  8.      }
  9.  
  10.      public function get model():MyModel
  11.      {
  12.           return _model;
  13.      }     
  14.  
  15.      public function setValue(val:int):void
  16.      {
  17.           model.value = val;
  18.      }
  19. }

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:

Actionscript:
  1. public class LoginCommand implements Command
  2. {
  3.      public function execute(event:CairngormEvent)
  4.      {
  5.          ModelLocator.getInstance().isLoginPending = true;
  6.      }
  7. }

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...

Actionscript:
  1. //In your Application.mxml
  2. <control:LoginController id="controller" model={ModelLocator.getInstance()}/>
  3.  
  4. //In your controller class (which is a subclass of Cairngorm's FrontController)
  5. protected override function executeCommand (event:CairngormEvent):void
  6. {
  7.  event.model = model; //store model reference within the event
  8.  super.executeCommand(event);
  9. }
  10.  
  11. //In your command(s)
  12. public function execute(event:CairngormEvent):void
  13. {
  14.     var model = event.model;//here you have access to the reference
  15. }

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

Abstract Factory Pattern

In previous posts I talked about the Simple Factory and Factory Method patterns. Now it's time to look at the Abstract Factory pattern.

All factory patterns are examples of creational patterns. In other words they help make the system independent of how objects are created by hiding (encapsulating) the instantiation process.

The Factory Method is an instance of a class creational pattern - it uses inheritance to decide the object which is to be instantiated, while the Abstract Factory is an instance of an object creational pattern - it delegates instantiation to another object (much like the Simple Factory we looked at earlier).

The Abstract Factory is used to create families of objects which are related or dependant (in fact the delegated object frequently uses factory methods to perform the instantiations). To get an idea of what this all means let's get back to the analogy involving music...

Every good rock, country or jazz band is comprised of various members. For arguments sake we will restrict the line up to one singer, one guitarist and one drummer.

Below I've created some fictional band line-ups. Rather than use real names I've called the rock singer RockSinger and the country drummer CountryDrummer etc. These families don't necessarily need to have mutually exclusive members - for example it is quite possible that you will find a musician who plays in both a rock band and a jazz band. You can see how the guitarist for the rock band is also the guitarist for the country band (RockCountryGuitarist), and how the drummer for the rock band also plays drums for the jazz band (RockJazzDrummer). Nevertheless each band can be thought of as a 'family' of members.

in the lists below, 'shared' members are a different colour...

Rock Band:

  • singer : RockSinger
  • guitarist : RockCountryGuitarist
  • drummer : RockJazzDrummer

Country Band:

  • singer : CountrySinger
  • guitarist : RockCountryGuitarist
  • drummer : CountryDrummer

Jazz Band:

  • singer : Jazz Singer
  • guitarist : JazzGuitarist
  • drummer : RockJazzDrummer

If you were to look at the members for each band you would hope to see something like this:

Abstract Factory trace

From the above diagram you can see that our moon-lighting guitarist and drummer do indeed play for more than one band. You can also see how at the end of the day we still have three families of related/dependent objects (i.e. three bands).

In diagrammatic form this is the class structure we want to achieve (click to see full picture):

Abstract Factory Class Diagram
note: italics represent abstract classes

The diagram shows that our client code will either instantiate (or more likely be passed) a concrete factory. For our example we will instantiate all of the factories directly in the client code, but in the real world it is expected that an object further up the project's chain would make the decision about what factory is needed and pass it to our client. In this way our client code would not need to care what factory it receives - it can treat all factories in the same way and generate the correct objects from it.

If you want to think of an example relating to software, we could be looking at families of operating-system-specific UI components, or families of drivers which depend upon the performance of your machine (e.g. HighResPrintDriver, HighResDisplayDriver, LowResPrintDriver and LowResDisplayDriver). The client code would know how to instantiate print-drivers and display-drivers but it does not have to care about what resolution drivers it is dealing with. The object higher up the chain can make that decision based upon a configuration file or some other application-instance-specific data.

Once we have our factory we can call methods on it such as createSinger(), createGuitarist() and createDrummer(). The factory is responsible for knowing and returning the appropriate members.

the code for this is very similar to the previous example, so I'm going to make it available for download without stepping through it all (if you get stuck, look back at the other posts on factories and refer to the class diagram above). Once again, take note of how generic objects are being passed back (AbstractSinger, AbstractGuitarist and AbstractDrummer). The client code doesn't need to worry about the specifics, it only needs to operate upon these more general types, which means that if we get new combinations down the line, or if we want to add completely new bands/members we can do so with the minimum of disruption.

The code can be found here.

No comments

Factory Method Pattern

In my last post I talked about how to use a Simple Factory to encapsulate areas of code that are likely to change. Continuing on with the same music example I'd like to now go over the Factory Method Pattern.

The purpose of the Factory Method Pattern is to link up two or more separate but related class hierarchies. The Factory Method lets a class defer instantiation to subclasses ( you will see what that means by looking at the following example code ) - if this is not what's happening then you are not using the Factory Method Pattern - it is amazing just how many tutorials will show you an example of the Simple Factory and tell you it is the Factory Method Pattern.

In our last example we had one class hierarchy, consisting of the abstract class AbstractSong, and its three subclasses RockSong, CountrySong and DanceSong.

In this example we have a second hierarchy, consisting of the abstract class AbstractCoverBand, and its three subclasses RockCoverBand, CounrtyCoverBand and DanceCoverBand.

It is obvious that classes from both these hierarchies are related to each other. If your wife-to-be asks you to hire a covers band for your wedding night, and some thrash metal group turn up to play a cover of Dolly Parton's "I will always love you", you may think it's the epitome of cool, but it may not be such a good move for your marriage. So, when you want someone to play a country song you will require a country covers band, when you want someone to play a rock song ... you get the picture.

It is often said that "the Factory Method defines an interface for creating an object, but lets the subclasses decide which class to instantiate" - this can be a little confusing. The subclasses don't technically decide anything. What this means is that by instantiating a particular subclass, the factory method is able to return the correct class from the related hierarchy.

Let's take a look at the example. The full code can be downloaded here.

We've got rid of our SimpleSongFactory file and we now have four new files, AbstractCoverBand, RockCoverband, CountryCoverBand and DanceCoverBand. We have also added a new method to the song classes. As long as you followed through the Simple Factory tutorial, we should be able to zip through the new files with little or no comment:

Actionscript:
  1. //Code for AbstractCoverBand
  2. package
  3. {
  4.     public class AbstractCoverBand
  5.     {
  6.         private var _name:String;
  7.  
  8.         public function AbstractCoverBand(name:String)
  9.         {
  10.             this.name = name;
  11.         }
  12.  
  13.         public function get name():String
  14.         {
  15.             return _name;
  16.         }
  17.  
  18.         public function set name(value:String):void
  19.         {
  20.             _name = value;
  21.         }
  22.     }
  23. }[

As with the other abstract class, common functionality is put here. To keep things simple we're not trying to prevent someone from instantiating the abstract class, and our intention is made clear from the name (remember: actual abstract classes are not supported in AS3).

I'll just show two of the three subclasses here:

Actionscript:
  1. //Code for RockCoverBand
  2. package
  3. {
  4.     public class RockCoverBand extends AbstractCoverBand
  5.     {
  6.         public function RockCoverBand(name:String)
  7.         {
  8.             super(name);
  9.         }
  10.     }
  11. }
  12.  
  13. -------------------------------------------------------------------------
  14.  
  15. //Code for DanceCoverBand
  16. package
  17. {
  18.     public class DanceCoverBand extends AbstractCoverBand
  19.     {
  20.         public function DanceCoverBand(name:String)
  21.         {
  22.             super(name);
  23.         }
  24.     }
  25. }

Again, to keep it simple nothing is really happening here other than passing in a string name and passing that on to the superclass to be stored.

All our song classes now have an added method called findCoverBand(). This is our factory method. All of the subclasses of AbstractSong will be required to override this method and provide specific functionality for it - i.e. return the coverband object which is relevant to them. Because this object will be of the general type AbstractCoverBand, the AbstractClass need not know anything specific about that particular object. If the abstract class needed to do something to this object it could do so without knowing the specific type. Here we can see that instantiation of the object is being deferred to the subclasses - this is what defines the Factory Method Pattern.

Below is an example of the modified code for RockSong. Notice that the factory method returns an object of type AbstractCoverBand. Nothing else has changed:

Actionscript:
  1. package
  2. {
  3.     public class RockSong extends AbstractSong
  4.     {
  5.         public function RockSong(artist:String, title:String)
  6.         {
  7.             super(artist, title);
  8.         }
  9.  
  10.         public override function findCoverBand():AbstractCoverBand
  11.         {
  12.             return new RockCoverBand("Rock Of Sages");
  13.         }
  14.  
  15.         public override function danceToTheMusic():void
  16.         {
  17.             trace("I AM MOSHING LIKE A MADMAN");
  18.         }
  19.     }
  20. }

Remember also that the AbstractSong class will need to implement the following method, which is overridden by the subclasses:

Actionscript:
  1. //Throws an error if someone tries to invoke this method without overriding it in a subclass
  2. public function findCoverBand():AbstractCoverBand
  3. {
  4.     throw new IllegalOperationError("Abstract methods must be overridden");
  5. }

Finally we can take a look at the modified Main class. I've cut out everything which is unnecessary, so that we can just check we are getting back the right cover band for the job:

Actionscript:
  1. package {
  2.     import flash.display.Sprite;
  3.  
  4.     public class Main extends Sprite
  5.     {
  6.         public function Main()
  7.         {
  8.             var song:AbstractSong = new DanceSong("SomeName", "SomeTitle");
  9.             var coverBand:AbstractCoverBand = song.findCoverBand();
  10.             trace("The cover band are: " + coverBand.name);
  11.         }
  12.     }
  13. }

As you can see, at this point we know what type of song we want and so we can instantiate RockSong, CountrySong etc (I'm just passing any old string in for band and title, as for this simple example they are irrelevant).

Once we have the instance of the song we can find out what cover band are best suited to play it, and we can be sure that we will get back an instance of the correct cover band. If you create a new RockSong, you will get back the band object most suited to playing that song.

CHANGE please
If you think back to the previous post, I mentioned protection from change - to my knowledge this is essentially what all design patterns are about. I talked about a design principle that says you should encapsulate areas of code likely to change from those which are not likely to change. Well, another design principle is that your code should be "open for extension but closed for modification". This means that it should be easy to add new functionality, and that you should be able to do so without having to modify existing classes (because that leads to an increased chance of breaking something that already exists and works).

SimpleFactory doesn't pass the open/closed test - we extracted changeable code in to its own class but we still need to open up and modify that class when change happens (this doesn't mean that SimpleFactory is bad, to the contrary it is very useful in certain circumstances). However, the additional effort used to set up the Factory Method Pattern really pays off when change happens. Imagine we need to add a Jazz song and a Jazz cover band. To do this we add new files, but we don't need to change any existing files (hurrah!).

Once we've added those files we simply instantiate an instance of JazzBand in our client code, and everything should work as expected.

1 comment

Next Page »

Bad Behavior has blocked 399 access attempts in the last 7 days.