Notes on learning Cairngorm
Friday, September 12th, 2008Here is how I added Cairngorm to my skill-set (after first gaining enough Flex experience to understand why you would use an architectural framework).
David Tucker’s 5-Part Series
David’s excellent articles and accompanying videos are what I would highly recommend starting with.
- Getting Started with Cairngorm - Part 1
- Getting Started with Cairngorm - Part 2
- Getting Started with Cairngorm - Part 3
- Getting Started with Cairngorm - Part 4
- Getting Started with Cairngorm - Part 5
CairngormStore Example
Or rather Douglas McCarroll’s update of Chen Bekor’s ModifiedCairngormStore. Douglas updated it for Cairngorm 2.2.1 and Flex 3.
10 Tips for Working with Cairngorm
Jesse Warden’s 10 Tips for Working with Cairngorm. Tip #10 about not having nested views dispatch CairngormEvents (but rather dispatch regular events — or your own custom events that extend the event class — to the main view which would then dispatch a CairngormEvent) is a best practice to keep in mind when studying the CairngormStore example.
Adobe Consulting’s 6-Part Article
Steven Webster and Leon Tanner of Adobe Consulting wrote Developing Flex RIAs with Cairngorm microarchitecture. The article has a lot of really good information in it and uses the CairngormStore as an example (although you will want to get the updated CairngormStore from the link above).
Here are some nuggets I gleaned from the articles:
Nugget #1
…resist the opportunity to scatter state all over your application as strings, numbers, Booleans, and all manner of other primitive objects. …we strongly advocate that the client hold the data — as state, model, or whatever you want to call it — as objects that have semantic meaning.
Source: part 2, page 4
The use of value objects (or data transfer objects) was brought up in other places and is not specific to Cairngorm. Still, it is good stuff that bears repeating.
Nugget #2
When you create components that rely upon client-side data, it is all too easy to create a direct reference to a Singleton model, such as
ShopModelLocator. Indeed this is true throughout the application. We discourage this approach. Instead, consider passing the model and/or its properties down through a hierarchy of your view components, for a cleaner and more thoughtful solution.
Source: part 2, page 7
The goal is to make components more reusable. If you have components importing the modelLocator, using the getInstance method, and then binding directly to data in the Cairngorm modelLocator instance, then those components are coupled to your project and/or the Cairngorm framework.
The argument behind not using CairngormEvents other than in your main view (Jesse Warden’s tip #10 from above) is the same reasoning here — reusablity and loosely coupled components. Ideally your components could be used outside of the Cairngorm framework.
The CairngormStore example follows this in some places, but not in others. In Main.mxml, for instance, a ProductVO is “injected” into the selectedItem attribute of the <details:ProductDetails> component. However other components, such as ProductsAndCheckoutViewStack.mxml, import the ModelLocator and use ShopModelLocator.getInstance().
Regarding the CairngormStore and best practices, Alistair McLeod states in a comment on his blog that “…you make a good point with CairngormStore - looking at the application now, it definitely does not advertise our best practices of building applications with Cairngorm, and that’s something else we want to rectify…”
I am still trying to fully understand best practices regarding reusability. There is a critique of Cairngorm (or rather a certain use of the Model Locator pattern) here where the author mentions some of this. Another blog post on Cairgorm with some discussion about the Model Locator and coupling components to it is here.
(And just when I thought I was beginning to understand reusability, I saw this session from 360Flex about there being two “levels” of reusability — loosely-coupled components and polished, fit for cataloging/distribution components. The gist being that a truly reusable component takes a lot more time to do and involves such things as allowing css styling and programming default behaviors.)
Nugget #3
Developers should always seek to extract these classes from the Cairngorm architecture. Pulling business logic out of commands and encapsulating into classes is a classic implementation of Extract class refactoring.
Source: part 4, page 5
This is in reference to the AddProductToShoppingCartCommand in CairngormStore. The execute function of this command class just calls a function on shoppingCart stored in the model locator.
-
ShopModelLocator.getInstance().shoppingCart.addElement(shoppingEvent.product, shoppingEvent.quantity);
Rather than have a lot of complex business logic associated with shopping cart behavior in the AddProductToShoppingCartCommand class, such business logic is encapsulated in a ShoppingCart class (which, in the CairngormStore example, was stored in the model folder.)
Nugget #4
…you and your team will approach the addition of each and every feature to a Cairngorm application in the same way. In short, you will add an event to the controller, register it with a Command class, and implement the Command class to do all the work. With this approach you can drive the development of your application with feature after feature, in a consistent, predictable manner that scales well.
Source: part 4, page 6
This is a good review of the flow in Cairngorm and the benefits of using an architectural framework.