Architectural Atrocities, part 10: Cairngorm’s Service Locator

In this installment of the Architectural Atrocities series I’ll continue on the Cairngorm theme. This time it’s something that is truly an architectural atrocity if there ever was one, and one of the ugliest things I’ve seen in such a high profile piece of software that Cairngorm is (a fact that still baffles me): Cairngorm’s Service Locator.

The last post stirred up quite some debate and I’d like to thank everyone who commented on the post. I’m amazed that people still post comments (by coincidence to the day) seven months later.

The Cairngorm ServiceLocator is, at least on the surface, an example of the J2EE pattern of the same name. There is a debate whether ServiceLocator is just another form of global variable or if it is more like a factory. I’m on the side of global variable, but notable persons like Martin Fowler thinks that ServiceLocator has merit. On the subject of the pattern I will not judge, however I will say a few things on Cairngorm’s variant.

In short a Service Locator is a registry of named services and provides a global access point for these. The idea is that you can load up the service locator with references to specific services, but the code that asks for them only knows their interface.

The Cairngorm variant provides a globally accessible registry for storing references to RemoteObject, HTTPService and WebService objects. Only. If you have custom services of any kind ServiceLocator doesn’t help you. You can’t load the ServiceLocator with objects willy-nilly, instead you have to subclass it and create the service objects in the subclass. This provides some of the abstraction that the ServiceLocator pattern is meant for — you can declare another subclass when you test, for example — but it’s quite limiting in its design. On the upside it makes it possible to set credentials on all services at once, which can be handy.

The way you use the ServiceLocator is to subclass it in MXML and declare the services you have. When you need to access the services you call ServiceLocator.getInstance() and use either getRemoteObject, getHTTPService or getWebService and pass the ID of the object you are interested in.

But wait a minute.

ServiceLocator.getInstance() you say? How does that give me a reference to the subclass where I declared my services?

The answer is, of course, bastardized object oriented black magic at it’s worst. When the subclass is instantiated, which it must be for this to work, it will run the superclass’ constructor which will set a global variable to this — let’s repeat that: the constructor of ServiceLocator sets a global variable to a reference to an instance of the subclass. This global variable is returned by ServiceLocator.getInstance().

But what if I declare two subclasses of ServiceLocator? Oh, why, then an exception is thrown when the second is instantiated, of course!

It is mind boggling how anyone could come up with something so byzantine and have the audacity to use the words “best practice” in connection with it. Just the idea of subclassing a Singleton should start the alarm bells ringing as loud as they go, not to mention subclasses affecting the workings of their parents as a side effect of them being instantiated. I can’t find words to describe all that is wrong with this.

If you so badly want to be able to access your services globally, why not just use Application.application.services or some something similar? (Not that I’m saying that it would be a good solution, it might just be a less insane solution.) Why go to such lengths and create something so profoundly appalling as Cairngorm’s ServiceLocator if all you want is global access to named objects? And why, when there’s a perfectly workable pattern that provides the same kind of solution, use the same name but invent something that uses none of the good parts, but all of the bad (and throw in some more bad things while you’re at it)?

I think that not only is the code atrocious, but the fact that the (new and updated) introductory articles on Cairngorm completely gloss over what is going on is disturbing. It doesn’t explain why you suddenly should use ServiceLocator.getInstance(), when you just previously declared a class called Services, how the things you declared in that class end up in ServiceLocator, and it there’s no mention that it all hinges on the Services class being instantiated exactly once.

Service Locator is surely the worst of Cairngorm and I would go so far as to say that if you think there’s nothing wrong with it, you shouldn’t be writing software.

24 Responses to “Architectural Atrocities, part 10: Cairngorm’s Service Locator”

  1. Joseph Burchett Says:

    Oh my, I have been on the rail on which MVC framework to use for my next Flex project and well… It seeming like more and more I am leaning towards PureMVC. I am curious on your thoughts of that framework… Clearly there seems to be certain aspects of Cairngorm that are flawed and from what I have read it doesn’t do so well when dealing with really modular applications.

    Makes me wonder why so many Flex shops use this framework, odd. But yeah good post :-)

  2. Theo Says:

    I use Mate, because so far it’s the only Flex application framework that hasn’t got fundamental architectural flaws (and besides, it’s quite good).

    I don’t really think that PureMVC is a good choice for Flex applications, but that’s another post or two. I’ve mentioned some of the reasons here: http://stackoverflow.com/questions/37043/flex-mvc-frameworks#37566 http://stackoverflow.com/questions/108889/objectively-what-are-the-pros-and-cons-of-cairngorm-over-puremvc#109038

  3. Bjorn Schultheiss Says:

    I don’t agree that Mate doesn’t have any fundamental architectural flaws.

    Mate’s EventMap does not allow you to Type any of your RPC returns, where Cairngorm uses the Delegate pattern. It seems pretty hackish.. for speed rather than quality.

    I’ve started on a new framework Intravenous http://code.google.com/p/intravenous

    Although its only a month old I think its already a substantial improvement on the other frameworks.

  4. Theo Says:

    @Bjorn/typed RPC returns: don’t blame Mate for how Flex RPC works. If you want to assign a static type to an RPC call you have to do it yourself, regardless framework. Seems like an odd detail to pick on, considering that we’re talking about application frameworks — and it’s neither an architectural nor a fundamental flaw (if a flaw at all). It’s not like you can’t easily create delegate-like classes and call them with AsyncMethodInvokers if you want more control (in fact, that’s what I usually do).

    I’ll take a look at your framework, I think it’s great with more options, and I like your four features, but you may want to add some more documentation.

  5. Bjorn Schultheiss Says:

    Hey Theo, I figured the point of your article was to bring attention to the mistake of using ServiceLocator.getInstance() within Cairngorm business delegates. Having a client side interface for the remote services is 1 of the advantages of Cairngorm over Mate. The use of the Singleton within the Delegate’s constructor is a very poor implementation, although Mate provides no alternative for the implementation of these delegates and responders.

    When I get some proper documentation and diagrams for Intravenous I’ll let you know. I’d appreciate your critical perspective ; )

  6. Theo Says:

    @Bjorn: no, you misunderstand. This article isn’t about how you work with the ServiceLocator in delegates, it’s true that that too is really ugly (and I actually have notes for an article about that too) — but it’s ugly on a more manageable level. What I’m after is the way you set up your ServiceLocator, the relation between Services.mxml and ServiceLocator.


    Now, to tackle your point anyway: who says Cairngorm has business delegates? I don’t see any. I see a lot of people talking about Cairngorm and business delegates and how to use the “pattern” with Cairngorm. But saying that Mate hasn’t got them and Cairngorm does is like saying Mate has the presentation model pattern, but Cairngorm doesn’t — just because a lot of people are using it with Mate, but almost no one is using it with Cairngorm.

    If you like business delegates, use them in your Mate-based applications, what’s stopping you? It’s just a class with a bunch of methods. Instead of using ServiceLocator.getInstance().getRemoteObject("foo"), set up an injector.

    It might not be the best fit, so you might need to modify it somewhat, but since the purpose is to encapsulate the service call the specifics of the implementation shouldn’t matter. I usually make the “delegate” dispatch events (for example ResultEvent and FaultEvent) instead of using call and IResponder, because it works better with AsyncMethodInvoker. It’s not identical in implementation, but it does the same job. Ask around in the Mate forums and I’m sure you will get a couple of different perspectives on how to achieve the same goal as business delegates in Cairngorm (but a bit more elegantly).


    Oh, and perhaps you should remove some of the comments in Intravenous so that it’s not so obvious that they are cut and pasted from Cairngorm =)

  7. Bjorn Schultheiss Says:

    Theo,

    I read through your article a second time. The first time I skimmed it.

    It’s gold! You’re like a mixture of chef Ramsey and Chuck Norris bringing to justice those who commit atrocities of architecture with swift and severe punishment. Disturbingly entertaining. It will be interesting to see if anyone justifies any of the points you raised.

  8. Theo Says:

    Thanks Bjorn, and don’t forget to let me know when Intravenous is ready enough that you’d like my input on it. I looked at the code briefly today, but I think I need some explanations to make sure that I’m not misunderstanding things.

  9. Joseph Burchett Says:

    Well I went through and read the other articles you have submitted on the topics of Cairngorm and other frameworks… And they have been some interesting reads and you pointed out good points. The only thing that gets me is that if Cairngorm has such huge flaws why is this framework so widely used and expected by so many Flex based employers? Based off what you are saying there are a lot of developers who are learning some pretty bad coding habits or “anti-patterns” as you stated.

    Personally I am new to this whole framework stuff, and been trying to decide on the best fit for my application, and there are just so many frameworks out there, and more keep popping up like every other day, it’s a bit overwhelming. Wish I had the time to try them all… ANYWAYS, good stuff.

  10. ryan Says:

    @Joseph Don’t feel intimidated by employers asking for Cairngorm, it’s really just a bullshit test to see if you are at an apropriate skill level to understand at least what the advantage/disadvantage of using a framework can be.

    Sadly many percive Cairngorm as being a standard due to the fact that it is one of the oldest Flex frameworks in existance and the fact that Adobe have provided so much support.

    There are many frameworks out there and they all combat various problems but don’t be suprised if you never find “the” framework because if it existed you would not be reading this post… Do take the time understand frameworks, after one the rest are a breeze…

  11. Theo Says:

    @Joseph

    Cairngorm’s wide-spread use has many explanations. The most important one is probably that for a long time there wasn’t any other application frameworks for Flex. Since Cairngorm was the Flex application framework for a long time many have invested time and money in applications that use it, and are (understandably) reluctant to drop it. Then there’s the fact that Cairngorm is sort of backed by Adobe since it’s main developers work for Adobe Consulting.

    You may ask why no one created an alternative quicker, given the state of Cairngorm, and to that I can only speculate: the small size of the Flex community and the relative inexperience of the developers in it are my guesses. That last point is still a big factor; I don’t think that most Flex developers really understand the issues involved. I’m quite horrified that many in the community seem to think that there’s some kind of controversy around whether or not global variables are a good idea — the rest of the software development world moved on from that twenty years ago. It all reminds me of the intelligent design debate.

    I know that quite a few would say something about Cairngorm being easy to learn and whatnot. I don’t consider that to be a particularly good argument. It’s easier to make a mess than to clean up, so what?

    Cairngorm is the Visual Basic of Flex: you can get things done, but it will give you a lot of bad habits.

  12. Joseph Burchett Says:

    Yeah, Ryan I think you may be right… They say that they expect you to know those things, when they are just probably looking for some one who has experience working with that sort. Also id love to take my time on choosing the right one, but sadly time is never on my side :-(

    And Theo yeah, I agree with you on all the stuff you have been saying so far… Crazy stuff, especially that line “Cairngorm is the Visual Basic of Flex” vomits a little in the mouth the very thought of ever having to do visual basic or anything with the word “basic” in it again makes me a bit sick to the stomach. Id prefer C++, java, C#, python, HELL just about anything then having to work in VB again…. I just don’t like working in it.

    ANYWAYS, I think I will take a peak at PureMVC but I am probably going to go with Mate. Also if you listen to some of the archived episodes of the Flex Show http://www.theflexshow.com/blog/ they talk to the creators of PureMVC, Mate and a bit about Cairngorm

  13. Flexible RIA Architecture: PureMVC and Mate « shaun smith Says:

    [...] or more Event Maps: loosely coupled goodness. Mate also employs Dependency Injection instead of the Service/Model Locator pattern used by Cairngorm and PureMVC. And no Singletons! Suitably [...]

  14. Jack9 Says:

    “I’m quite horrified that many in the community seem to think that there’s some kind of controversy around whether or not global variables are a good idea — the rest of the software development world moved on from that twenty years ago.”

    No, “they” didn’t. There are exceptions to every rule and sometimes the exceptions prove the rule, i.e. logging, database connections. This declarative “good vs bad” is always so one sided, it’s sad on multiple levels.

  15. Theo Says:

    @Jack9 you’re talking fringe cases and necessary evils, it’s hardly proof of controversy. I think it’s fair to say that there is a consensus on the badness of global variables, and saying that there are exceptions doesn’t change that fact. Of course there are exceptions, there are exceptions to everything, it’s the real world! It’s hardly news.

  16. mzx Says:

    first joke: anybody doing any real applications here?)

    i agree that mate is more promising but:

    u can find more developers having experience (so called bad habits) in cairngorm than mate

    mate is still in beta while cairngorm last bug fixed 2 years ago(believe me its not too funny to accidentaly found memoryleaks in framework after 6 month of development)

  17. Theo Says:

    u can find more developers having experience (so called bad habits) in cairngorm than mate

    Fair enough, if quality is of no concern.

  18. Alexander Arendar Says:

    Theo, quality has nothing to do with the choice of framework. I think each good framework can be employed to attain a good quality once the person doing the job got a piece of brain in the pocket.

  19. Theo Says:

    quality has nothing to do with the choice of framework

    What other measure than quality is there?

    I think each good framework can be employed to attain a good quality once the person doing the job got a piece of brain in the pocket.

    Well, yeah. But that’s an empty statement. A good framework can be used to make good applications by good programmers. Go figure. What else are you doing but a judgement of quality when you say that? Now, what about a bad framework, or should I say a low quality framework?

    Of course a good programmer can make good software with bad tools, but it’s very unlikely that you would get many good programmers by picking a bad tool. The good programmers are good partly because they can tell good from bad, they know quality, and they tend to use the good tools.

    Now, that last piece could be interpreted in two ways in the light of the number of Flex developers that work with Cairngorm. I will let you guess which interpretation I think is right. A hint is that quality is not decided by majority vote.

  20. NewToCairngorm Says:

    Hey Theo,

    I’m new to Flex and Cairngorm.While I’m using ServiceLocator,I do run into the problem: Error: C0001E: Only one ServiceLocator instance can be instantiated.

    My Code is like this:

    In Serives.mxml:

    In Delegate.as,I have snippets:

    this.service = ServiceLocator.getInstance().getHTTPService(“statistServ”);

    In Main.xml,snippets like:

    this wonderful little Error message pops up the minute I load a second instance of some module which requires httpservice.

    Is there any way to resolve this problem without switching to another Framework?

    Best Wishes,

    Shuo from China

  21. Theo Says:

    Hi Suho. This is not a questions and answer site. Try http://www.stackoverflow.com

  22. NewToCairngorm Says:

    Thanks any way!

  23. Codetoglory Says:

    Hi Theo,

    I really liked your articles and you make lot of good points. I feel cairngorm is so widely used and supported by Adobe because of the fundamental fact that Adobe guys are not really good at object oriented paradigms. They have an eye for good UI design but lack architectural design insight to understand the down side of many things that you raise here like service locator and model locator.

  24. Michel Boudreau Says:

    I have to admit Theo, I love how passionate you are about bad software practices that Adobe seems to ignore altogether. I’m in the same boat as you and loathe cairngorm.

    Keep up the good work :)

Leave a Reply