Cairngorm – A glamorous pitfall, Is it? – Part I


When I started using Flex a few months back, the very first tings thing that crossed me was the fan-following for Cairngorm. It was amazing how could a framework be so popular, but they claimed to solve all the problems. It seemed a little good to be true, but was worth trying. Over a period of last two months, I have now realized that Cairngorm has quite a few shortcomings that leads to be an overly glorified framework that can not scale for any Enterprise Application, without any changes. “Without any changes” is the key here. With this Article, I start off a series of articles that is my attempt to explain why I feel Some things in Cairngorm need to change.

“Cairngorm is an implementation of design patterns that the consultants at Adobe Consulting have successfully taken from enterprise software development (with technologies including J2EE and .NET) and applied rich Internet application development using Adobe Flex.” – Quoted by Adobe Labs

The benefits of the Cairngorm architecture are realized when developing complex RIA applications with multiple use-cases and views, with a team of developers, and with a multi-disciplinary development team that includes designers as well as creative and technical developers. – Quoted by Adobe

Steven Webster follows up with series of articles explaining details on how to use Cairngorm. The goals that Cairngorm helps us achieve are:

  1. Keeping State on the Client
  2. Architecting the View
  3. Feature-driven Development
  4. Server-side Integration

In this article, I will talk about the “Keeping State on the Client” aspect of the Cairngorm and I will be referring to the “Cairngorm Store Web 2.1” for any examples/references.

Steven introduces us to the Value Object pattern and the Model Locator pattern. As he quotes:

Many developers are familiar with the concept of MVC or Model/View/Control in application development, and wonder where state fits into this discussion. Quite simply, the state is the model.

In this case the ValueObject Pattern is one where you can use objects on the Client (Flex) and pass the same information to the back-end. If you are using LCDS/BlazeDS, then you get the benefit of using the same object in both the tiers. This is a great value add as developers do not have to maintain the overhead of heavy conversions on objects. Also, there are some tools available like XDoclet that will allow you to generate ActionScript objects from your Java POJOs and hence achieve quick and speedy results.

Model Locator pattern is the one that I find is the glorified pitfall. As Steven quotes again:

The Model Locator pattern is unique because it is not a pattern we borrowed from the Core J2EE Pattern catalog. Instead, we created this pattern particularly for Flex application development.Our motivation was to have a single place where the application state is held in a Flex application and where view components are able to “locate” the client-side model that they wish to render.

Great thinking, but the implementation is not what it should have been. A few of my observations:

1. Adobe has provided a marker interface “ModelLocator” which I do not understand why it is needed. The only driver that I can think of is to follow the OO practice – Develop against Interfaces and not implementations. Even though you would like to have your state/model divided into many ways, this does not makes sense. A Marker interface is used is you want to use things at Reflection, but in this case there is not such usage and is redundant. Model/state could have very well lived in the even without the Marker Interface

2. Use of singletons is where I believe which breaks the things. Steven quotes:

Having all the attributes on the Model Locator pattern as static attributes ensures that the Model Locator pattern is a simple implementation of a singleton. You ensure, for instance, that one and only one instance of a ShoppingCart exists per user.

Again, the intent is good, but the example that they took up is not at all good, is very bad. Let us take the example of the Cairngorm Store where they have used the Bindings to bind the Single Instance of the data to the view This simply couples the View with the State/Model and re-usability goes out of the window. <Kaboom/>. Code:

<details:ProductDetails
        id="productDetailsComp"
        width="100%" height="325"
        currencyFormatter="{ ModelLocator.currencyFormatter }"
        selectedItem="{ ModelLocator.selectedItem }" 
        addProduct="addProductToShoppingCart( event )" />

Consider a scenario, where in my application I want to use the component “ProductDetails” elsewhere, but as this component is now bound to the model/state, if I change the model, it effects the data elsewhere. Try adding the capability to compare the products, where you would like to re-use the same component to show the details in a comparative view. This component is useless and you can never get two different data sets to be bound to the same view.

But, do not just write-off this pattern – it is still very useful. All you folks who have ever developed the Web 1.0, know that a user’s session state is something that we have to manage in the HTTPSession and that was known as the state. You can use this pattern very well to do similar things like:

  1. Manage User’s Session State and use the same to check for authorizations;
  2. Show user;s navigation in the application. Almost all the applications have Breadcrumbs which should have just 1 state/model;
  3. Current View/navigation state of the user i.e. -> ViewStack indexes/TabView indexes

I am sure that there are more, but I find this pattern very useful in many ways; just have to be careful that over usage of the same would lead to some serious trouble.

Advertisements

10 thoughts on “Cairngorm – A glamorous pitfall, Is it? – Part I

  1. >>> Consider a scenario, where in my application
    >>> I want to use the component “ProductDetails”
    >>> elsewhere, but as this component is now bound
    >>> to the model/state, if I change the model, it
    >>> effects the data elsewhere.

    You mess. Not THE COMPONENT bound to the scenario, but AN INSTANCE of it. Feel the difference. So, when you need to add capability for comparing two (or more) products, you need to create two (or more) new instances of ProductDetails class. Also you need for them two new models in the ModelLocator.

    >>> 1. Adobe has provided a marker interface
    >>> “ModelLocator” which I do not understand
    >> why it is needed.

    This is Cairngorm approach to keep all data in the same place. Of course you may do it in you own way. You may duplicate data in memory how much you want.

    >>> Model/state could have very well lived
    >>> in the even without the Marker Interface

    I guess you meant ‘event’. Of course you can keep data in event… But what you should to do if there be many recipients of that data? Or you prefer to subscribe them all to that event, rather than use data binding?

  2. @serge – Maybe I should I have explained the complexity in my post, never to late. Consider a scenario, when you do not know ar compile time how many instances will you have. A user can choose to add components at run-time and how many model can you put on hold? Also, when writing the code, the component is bound to a model variable which again is picked up at compile time and not at run time, which means that when you can not re-use the components.

    Try adding multiple instances of the a dataGrid on runtime (which is creating instances at rum time), the logic becomes very complex (almost un-manageable with the model/state)

    >> This is Cairngorm approach to keep all data in the same place. Of course you may do it in you own way. You may duplicate data in memory how much you want.
    – How does a MarkerInterface helps on this one. Without the interface, the same was still achievable.

  3. The number one feature missing in most frameworks is “APPROACHABLE”. The guys who build things are typically more concerned with the features than usability. It’s kinda funny that we only think of usability in terms of the data interface of applications. It is also part of the programing reality. If we cannot get up to speed on it in a practical way it is in fact an immature concept when it comes to usability.
    🙂

  4. > @serge – Maybe I should I have explained the
    > complexity in my post, never to late. Consider
    > a scenario, when you do not know ar compile
    > time how many instances will you have. A user
    > can choose to add components at run-time and
    > how many model can you put on hold?

    If you don’t know how much models will be in future, you can keep an array of VO in the Model Locator. When you constructing the view, says comparing component, you will need an Data Provider (array of selected VO to compare) and an Item Renderer.

    > Also, when writing the code, the component is
    > bound to a model variable which again is picked
    > up at compile time and not at run time, which
    > means that when you can not re-use the components.

    No, you mess again. Reusing component, mean that you able to use once writing module in many projects. Particular component need and appropriate Value Object to render data. So, when you supply the same VO in future projects, you can use that component without any modifications – this is Reusing. But when you use multiple time the same module in the same project – this names Instantiating. You can create such instances of component how much you want; you can bind and moreover rebind it to any appropriate VO in Model Locator.

    > Try adding multiple instances of the a dataGrid
    > on runtime (which is creating instances at rum time),
    > the logic becomes very complex (almost
    > un-manageable with the model/state)

    I think it’s better for you reread carefully Webster’s articles.
    Of course you can’t add to Model Locator any principle new VO in runtime. It’s because you must implement its class at first. But when you need multiple VO – you should to use an array collection of it. There are no some special troubles with it. Moreover in Webster’s Cairngorm Store comparator of product is also implemented. So, somehow he founded a solution))).

    I agree with you that Cairngorm is complex approach to build you own programs. Before that you must do some plain projects and feel the needing of micro-architecture. Cairngorm solve many troubles with intercommunications of you modules. But you must thinking in Cairngorm to see gain of it.

    And any way, Cairngorm is just a one approach to build RIA. There are many others, choose somewhat else for you self.

  5. Pingback: CISNKY » links for 2008-04-23

  6. “I change the model, it effects the data elsewhere. ”
    That is rather the point 🙂
    More so, as long as your reusable component doesn’t use the Model inside it, but takes the properties of the model it needs as it’s own properties, as you show, then it’s utterly decoupled from Caingorm anyway. This is good for components you intend to reuse.
    i normaly start with Model references inside my view components and as and when they need to be reused elsewhere move the Model references to public bindables. I’d probably also rewrite from MXML to AS and/or code-behind at that point too.

    “Try adding the capability to compare the products, where you would like to re-use the same component to show the details in a comparative view”
    Why would I want to take a component for one thing, and reuse it for another ? I might want to put two ProductDetails in some sort of ProductDuelCompare for instance, or use them as renderers in a TileList, but I wouldn’t build compare functions into a ProductDetails view.

  7. Pingback: Recent Links Tagged With "designpattern" - JabberTags

Initiate your idea here...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s