Migrate from Cairngorm to Swiz

If you are a Flex developer you surely know and probably used the Cairngorm framework from Adobe. I have used it too for almost two years before I switched to Swiz. I don’t want to bitch against Cairngorm but for me and many others coding with Swiz offered a simplier way building a RIA because of less repetitive tasks (boilerplate code) and more flexibility. In this post I would like to show how easy it is to migrate an existing Cairngorm application to Swiz. More ore less it is about removing code which is always a good thing. Less code means less bugs and less maintenance so – more time for features!

In Cairngorm you have a few central classes which are accessible as singletons. In Swiz you won’t have any singletons in your code at all if you don’t want to but instead you will use the Autowire annotation to let Swiz wire things together for you using dependency injection aka Inversion of Control. These kind of classes are mainly models, controllers, delegates and services.

You can mix Cairngorm and Swiz at the same time while migrating so you are not forced to refactor your application at once but in an iterative way.

Let’s get started: Download the latest Swiz library SWC and add it to your project libs. If you want to check out the latest sources from SVN to compile the SWC on your own be sure to add the compiler parameter -keep-as3-metadata+=Autowire,Mediate.

To initialize Swiz you need at least one BeanLoader which will be the place where you declare models, controllers, delegates and services. The terminology “Bean” will probably change in one of the next Swiz releases. Imagine the BeanLoader as the place where you set up non-view classes.

Create a new MXML class and call it e.g. MyLoader and let it extend BeanLoader. Then change the namespace to org.swizframework.util.* so it will look like this:

<?xml version="1.0" encoding="utf-8"?>
<BeanLoader xmlns="org.swizframework.util.*">
 
</BeanLoader>

So let’s refactor your first peace of code. Let’s assume your ModelLocator contains a class ContactModel which holds a list of contacts. The ContactModel instance is bound to one of your views like:

[Bindable]
var modelLocator:MyModelLocator = MyModelLocator.getIntance();
 
<mx:List dataProvider="{modelLocator.contactModel.list}" />

Now remove the contactModel from your ModelLocator and add it to the BeanLoader so it will looks like this:

<?xml version="1.0" encoding="utf-8"?>
<BeanLoader xmlns="org.swizframework.util.*">
	<model:ContactModel xmlns:model="com.domain.project.model.*" />
</BeanLoader>

and change the view to this:

[Bindable][Autowire]
public var contactModel:ContactModel;
 
<mx:List dataProvider="{contactModel.list}" />

With the Autowire annotation we tell Swiz that we need the the ContactModel. It has to be defined public because otherwise Swiz is not able to inject the instance defined in MyLoader.
Now we have to tell Swiz to use the MyLoader where we have just set up our ContactModel. Switch to your main application MXML and add an event listener for preinitialize and define the event handler like this:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	preinitialize="preInitHandler()" />
	<mx:Script>
		<![CDATA[
			import org.swizframework.Swiz;
			import com.domain.project.MyBeans;
			private function preInitHandler():void
			{
				Swiz.loadBeans([MyBeans]);
			}
		]]>
	</mx:Script>

You see that loadBeans expects an array so you can define multiple BeanLoaders if you like.
In this case we have used autowire-by-type. This means Swiz will find the ContactModel because only one instance is defined in the BeanLoader. If you have classes of the same type in the BeanLoader you can also autowire by id. Only give the instance an id like e.g. id=”contactModel” and autowire it with [Autowire(bean=”contactModel”)]

With this refactoring we might have broken a Cairngorm command because now the flow looks like this

  • Command was invoked from a Cairngorm event mapped to in the FrontController
  • Command instantiated a Business Delegate and added itself as a Responder implementing the Responder interface
  • Business Delegate gets service from ServiceLocator and calls it
  • Service returns result/fault and the Command in this case Responder gets notified

With Swiz you have no FrontController, no ServiceLocator and the delegates are also only created once because they live in a BeanLoader. The Command will be replaced by a controller so it is easier to have multiple actions in one controller so you don’t end up with a ContactReadCommand, ContactAddCommand, ContactUpdateCommand or a switch statement in the command itself to determine which event came in.

To refactor do the following:

  • Move the contact service from ServiceLocator to MyLoader
  • Add the delegate to MyLoader
  • Create a new controller called ContactController extending AbstractController and add it to MyLoader

Your BeanLoader now looks smilar like this:

<?xml version="1.0" encoding="utf-8"?>
<BeanLoader xmlns="org.swizframework.util.*"
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:model="example.model.*"
	xmlns:ctrl="example.ctrl.*"
	xmlns:business="example.business.*">
 
	<model:ContactsModel />
	<ctrl:ContactController />
	<business:ContactDelegate />
	<mx:HTTPService id="contactService" />
 
</BeanLoader>

It is best practice to let delegates implement an interface so other classes only have to deal with a clean interface so the ContactDelegate interface looks like this:

package example.business
{
	import mx.rpc.AsyncToken;
 
	public interface IContactDelegate
	{
		function getContacts():AsyncToken;
	}
}

and the implementation like this:

package example.business
{
	import mx.rpc.AsyncToken;
	import mx.rpc.http.HTTPService;
 
	public class ContactDelegate implements IContactDelegate
	{
 
		[Autowire(bean="contactService")]
		public var service:HTTPService;
 
		public function getContacts():AsyncToken
		{
			return service.send();
		}
 
	}
}

You see that we simply autowire the service instead of having any call to a ServiceLocator.

Now the controller. The ContactController has two dependecies. We will need access to the delegate to call the service and to the model to store the result and both will be autowired:

package example.ctrl
{
	import example.business.IContactDelegate;
	import example.model.ContactModel;
 
	import mx.collections.ArrayCollection;
	import mx.rpc.AsyncToken;
	import mx.rpc.events.ResultEvent;
 
	import org.swizframework.controller.AbstractController;
 
	public class ContactController extends AbstractController
	{
 
		[Autowire]
		public var model:ContactModel;
 
		[Autowire]
		public var delegate:IContactDelegate;
 
		public function ContactController()
		{
		}
 
		[Mediate(event="loadContacts")]
		public function loadContacts():void
		{
			var call:AsyncToken = delegate.getContacts();
			executeServiceCall(call, contactsResultHandler);
		}
 
		protected function contactsResultHandler(re:ResultEvent):void
		{
			var ac:ArrayCollection = re.result as ArrayCollection;
			model.list = ac;
		}
 
	}
}

You see something new which is the Mediate annotation [Mediate(event=”loadContacts”)]
Instead of a FrontController which maps events to commands Swiz uses a concept called dynamic mediators. In this case we are using a primitive event and there are more sophisticated ways to implement dynamic mediators and also pass parameters (event member variables) etc.

So let’s say you want to load the contacts when your application starts simply add this line of code to the main application creationComplete event handler:

Swiz.dispatch("loadContacts")

Swiz is aware of all mediate annotations and has created event listeners and with the line above our controller method loadContacts gets invoked. You could also use an event class which does not need a special base class like the CairngormEvent but only flash.events.Event. For more info and some shortcuts and runtime validation read on here about eventPackages.

So let’s some up how the different layers of your application work together:

  • Declare models, controller, delegates and services in the BeanLoader and load them with Swiz.loadBeans
  • Views get the model autowired and can add data bindings.
  • Views dispatch events caused by user gestures with Swiz.dispatchEvent or Swiz.dispatch
  • Controller mediate events with [Mediate(event=”…”, properties=”…”)]
  • Controllers get models autowired which need to be changed by the controller.
  • If the controller calls a service autowire the delegate
  • Delegates autowire services and return the AsyncToken from the service call

I hope at this post you have learned some concepts of Swiz compared to Cairngorm and see that migrating from Cairngorm to Swiz means more decoupling and removing repetitive code. I had a large project with more than one year development spend on and refactoring was done in a short timeframe and reduced about 30% lines of code.

If you have more questions please drop a comment and/or join the mailing list.

18 comments to Migrate from Cairngorm to Swiz

  • Interesting. One of these days I will have to give Swiz a shot.

    Do you find it more difficult to keep track of all of the [Mediate]’s as compared to just checking the controller in Cairngorm? Is it tempting to place a lot of code into the new Controller that used to be a few Commands that each did one specific thing well? I like that Cairngorm is set up to wrap the single bits of functionality up in small/concise classes, but it can be a bit tricky at times to deal with command sequences.

    Where did most of your code reduction come from? Was it mostly because you no longer have the all command class declarations and removed Cairngorm controller? Did you see much difference in the final file size of your swf? Did you notice any difference in speed one way or the other?

    Sorry for so many questions, just seems like you have a good test case with your refactor.

  • Hi Shawn,
    for me it works good to keep track about the Mediates. Mostly it is sure which controller handles it and otherwise I use the search.
    To the code I think the controller code is better understandable than a couple of commands where you have repetitive code like creating the delegate in each command.
    The most code reduction was because of combining several commands in specific controller classes where I could re-use common code. Also having a BeanLoader instead of a ModelLocator, a FontController and a ServiceLocator and using Autowire replaced the singleton dependecies from all classes which makes it easier to replace the implementation behind especially when autowiring against interfaces.
    So it is not only the reduction of code but also the reduction of classes which gives a better overview of the project from my point of view.

  • Thanks for blogging this Sönke. It’s perfect timing as I am looking at Swiz right now having used Cairngorm it the past

  • Hi Sönke,

    We already do something like the BeanLoader in Cairngorm – we use an older-style untyped ServiceLocator (one singleton, yes) but then instantiate all our models, services (and sometimes other business objects) in it. We then use binding for dependency injection, which keeps things very simple and flexible – and it looks almost the same as your BeanLoader example above. Remember that all Cairngorm provides regarding singleton models is IModelLocator – so it’s not really that prescriptive about it, on most of our projects we’ve only used IModelLocator for a session/user model, and all our remaining models have been instance-based.

    I can see from your comments and the example that the number of distinct classes you have to write is reduced, but I’d like to challenge the assumption that this is a good thing – didn’t you find on a Cairngorm project that it was easy to find your command logic from the file names, without having to dig through the code? I think there’s a lot to be said for the design principle around lots of little classes, e.g. “doing one thing and doing it well” / “give a class only one reason to change” / “open for extension, closed for modification”. Looking at your controller above, wouldn’t you be constantly changing the source of the one class? I know on large Cairngorm projects we had enough trouble merging everyone’s changes to the addCommand() list in the Front Controller – to actually put the command logic in there as well would surely make things more difficult, and give you a lot less elbow room when you had to do a complex command… anyway, my two cents worth.

    Cheers,
    Robin

  • Being a recent Swiz convert, I’d like to address some of Robin’s comments. In the recent past I’ve been using Mate (which is also a great framework) but prior to that was a Cairngorm die hard.

    I have never heard of instantiating your models in ServiceLocator and would be curious as to why that is done. I am also not sure what you mean by “We then use binding for dependency injection”, as they are not the same thing and one does not imply the other. What do the bindings in your views look like? While its not prescribed/enforced by the framework, the traditional Cairngorm methodology has been to do things like which is obviously not optimal.

    I can relate to and agree with your sentiments that lots of small classes are better than a few gigantic ones, and in fact used to count that very reason as one of the things I liked about Cairngorm, but there is a happy medium. Swiz and Mate, in my opinion, encourage this happy medium. A basic example is that rather than having AddUserCommand, UpdateUserCommand, DeleteUserCommand, AddUserEvent, UpdateUserEvent, DeleteUserEvent (as well as some devs creating AddUserDelegate, UpdateUserDelegate and DeleteUserDelegate), as well as 3 addCommand() statements in your FrontController, with Swiz you would have a UserController, UserEvent and UserDelegate, and you would register UserController and UserDelegate in your BeanLoader. Counting the fact that ServiceLocator goes away, you’ve reduced the number of classes required for basic CRUD from as many as 10 down to 3. Yes, the reduction alone does not mean its better, but you have now consolidated all User related logic into a reasonable grouping. In a large app you might still have 30 controllers, but its better than 90 commands, 90 events and 90 addCommand()’s in my opinion.

    Your UserController is still closed for modification, unless something about your User object changes or the remote methods change, in which case you will have to update fewer classes than you would have in Cairngorm. I think your comment about the addCommand() statements is actually an argument in favor of the Swiz approach, because it allows different team members to work on different pieces of the app independently. Since there is no central registration required (other than BeanLoader which happens early and fewer times), once a team member is assigned a functional area (which is generally what controllers map to) they can work without affecting others.

    Cairngorm can certainly be beneficial in the fact that it prescribes a simple, repeatable process for adding features to your application, its well documented, widely known and easy for newcomers to learn. In my opinion, however, that simplicity comes at the cost of code duplication, inefficiency and brittle code.

    (Sorry for such a long comment, I should and probably will make this a post on my own blog.)

  • Tag after “things like” at the end of second paragraph got eaten. Was supposed to be: [mx:Label text=”{ ModelLocator.getInstance().someValue }” /]

  • Ben, thanks for your comment which exactly describes what I thought and tried to express in the post in the first place.

    @Robin: you are saying that you use binding for dependency injection. Do you mean by that something like:
    var modelLocator:IModelLocator = ModelLocator.getInstance();?
    If this is so this is no dependency injection aka inversion of control. The thing about dependency injection is the so called Hollywood principle: “Don’t call us, we call you”: http://en.wikipedia.org/wiki/Hollywood_Principle
    I think to have a better understanding trying out Swiz is probably the best because than you understand why it is brutally simple to use and offers so much flexibility.

  • […] Sönke Rohde » Migrate from Cairngorm to Swiz (tags: cairngorm swiz) […]

  • What about Swiz.dispatch(“loadContacts”)?

    Even if it doesn’t have an getInstance() it still hides a singleton, and any place where you use this it is as if adding an old Whatever.getInstance() call in your code.

    I guess one could wrap the calls to Swiz in a bean and have swiz autowire it into the class. Then it’d have dispatcher.dispatch(“foo”), but it requires more boilerplate code for any class needing the “dispatcher”.

    What’s your opinion on event bubbling?
    The swiz mediator could register itself to the systemManager and catch the events before they fizzle.
    This would liberate components from calling static Swiz methods and there’d be no extra injection boilerplate.

  • duh, forget it :)
    I just read newer posts on your blog.

  • Yep, for the record: Swiz supports now bubbling events and the BeanLoader contains a protected dispatcher instance which can be set in every bean loaded in a BeanLoader.

  • him_aeng

    Recently, I just finished my project yesterday. That project use .swc file that publish from flash cs3 using flex component kit heavily. So the problem with this approach was that your view code was boilerplate. I have to addEventListener with every button when the frame was entered. When I dispatch the view event to Cairngorm command I found many of same problem. It doesn’t work right, so sometime I have to write command code in view itself it look ugly and many line.

    Another problem with Cairngorm was my project rely heavily on message pushing from server and Cairngorm standard edition was not support because since version 2.1 Adobe decided to separated the enterprise feature to cairngorm (in this case is getConsumer() method) enterprise version, which use well with only LCDS and my project use BlazeDS, so the ugly happen again. I was force by Cairngorm to put consumer logic in view and modelLocator very ugly code.

    Now, I decided to refactor my project to use swiz and when I read the project code from http://www.returnundefined.com/2009/05/swiz-example-application-with-presentation-model-pattern, I felled it is lovely framework, It look fun to work with so today I will start to refactor my project with your awesome framework.

    So, only one question that I have.

    Is there any issue about working with message pushing with swiz like Cairngorm has?

  • him_aeng, you should be able to solve message push more elegant with Swiz. I would recommend to post your question to the swiz mailinglist to get feedback from the Swiz community.

  • him_aeng

    I waited for you and other swiz guru to answer my question. Please visit to http://groups.google.com/group/swiz-framework/browse_thread/thread/43a722a6ef92eec8

  • […] the web to read up a little more on Swiz and I came to an article by Sönke Rohde about migrating from Cairngorm to Swiz. The way Sonke deals with Swiz is a bit different than in Brian’s tutorial and it makes things […]

  • […] Sönke Rohde » Migrate from Cairngorm to Swiz (tags: cairngorm swiz) […]

  • […] Sönke Rohde » Migrate from Cairngorm to Swiz (tags: cairngorm swiz) […]

  • Shri

    I like to know, As in Caringorm we write custom events and can pass some values through commants. How it can be define in Swiz? Can anyone give sample code for same?