I had an errand to run yesterday and my peer at ESRIA, Brian Riley, had some interesting news, so it was a perfect time to call. After we discussed his good news, I then veered the conversation to lack of a formalized Mediator in Cairngorm to get his thoughts. Also known as “Abstract Brian”, he’s a self-proclaimed OOP Purist, always striving for writing the most maintainable, well architected code. He’s also a Cairngorm fan.
My positive feelings towards Cairngorm have waned in the past 2 years. There are a number of reasons for this. The first is that there are finally good alternatives such as MVCS, PureMVC, and Mate. The second is that one of the benefits of Cairngorm, RAD development (allowing multiple developers to work on the same code base) has never really been realized by me. Even in the Flex consulting & contracting world, I’m constantly on my own OR working with 1 other developer and we just communicate our changes to each other thus negating the need for a lot of sequestered abstraction. The third is that the newer frameworks have solved more for the GUI portion of Cairngorm, most notably the Mediator’s in PureMVC. The fourth reason was that, in the early days, if you were with a consulting firm you typically utilized Cairngorm. This was to make sure the client felt comfortable that you were utilizing an industry de-facto standard, and that they weren’t being given a code base that only your firm could maintain. That is no longer the case; as Brian said, Flex is easy. You give any traditional software developer a week with it with some guidance, and they’ll get it. The fifth is that it’s been 4 years… Cairngorm isn’t dead, but when you look at the competition’s resources (PureMVC & Mate’s documentation/examples/etc.), the lack of a formalized Mediator concept, and the still lacking of a solid push methodology, I’m more liable to utilize another framework.
Our original discussion was around 2 things. The first is that Cairngorm has no formalized Mediator. Meaning, there is no one to translate all of the Application Logic to Business Logic. Aka, “a user wants to save a Person Object they created” or “I’ve received confirmation that your Person Object saved, what View wants to know about this success?”. This is just breezed over in Cairngorm and all falls to the developer on where to do this. Most delegate the responsibility of running specific use cases (aka, dispatching events utilizing CairngormEventDispatcher) to the various View’s who handle those use cases. So, in practice, someone would create a login form in LoginFormView.mxml, and when the user clicks the submit button, they’d immediately run CairngormEventDispatcher. getInstance(). dispatchEvent(someCairngormEvent.LOGIN), or something to that effect. The pro’s are that no one else has to handle the details of the logging in process; whatever parent View houses the LoginFormView.mxml will just listen for a success or failure event dispatched from the LoginFormView.mxml. How the LoginFormView.mxml determines success or failure is up to debate. Does he bind to a state Singleton, and react to its data changes? Or, does he utilize the Universal Mind Cairngorm Extensions and wait for a callback? Either one will work. Bottom line, again, all of this logic is self-contained.
As your application grows, this delegation of use case handling and reacting to state becomes nested in a lot of your Views. This can become somewhat unmanageable when trying to debug, so what some people do is try to make one big View that’s smart, and he’ll delegate either data and/or state changes to his children, keeping them dumb and easier to debug. This in turn puts more weight & responsibility on them; aka, more code. Some people don’t have a problem with this. Utilizing code behind (external script source, extending AS using MXML, or AS extending MXML) allows the code to be in “smaller” chunks, and thus more easily manageable. I disagree with this statement, but a lot of people seem to be fine with this. To me, the work of handling events being bubbled up from child views, and determining which children need a state change is the sole responsibility of a Mediator. This is effectively what these parent View’s are doing, except they also have some other View-like responsibilities; making them in charge of 3 things, instead of the normal 2 (event happened so react, or received state change so update children). The point here is that this is a convention built out of need from utilizing Cairngorm vs. a formalized concept dictated by the Cairngorm framework. The closest we have is a good blog post by Farata Systems explaining how to utilize it.
PureMVC formalizes this concept which allows your View’s to focus on just being View’s and exposing methods & public setters for either state changes and/or data receiving. That’s really nice. Unlike code behind, it’s a formalized framework concept to help delegate responsibility of Application Logic to someone who’s sole job is to handle just that; mediation. Cairngorm just assumes you’ll figure it out, you’ll utilize code-behind to manage to code bloat, or you just don’t care because you don’t perceive the code as bloated. That last point is often the case with less design intensive Flex applications because there isn’t a lot going on in the interface beyond mediation. So, Enterprise Developers often don’t see the problem here whereas those from a design background like me get really irritated with the multitude of details a simple View needs to handle.
While PureMVC does not suffer from the “Singleton Problem”, it’s a real pain in the ass not having direct access to global data. Mediators are squarely on the front-lines of ensuring the View’s they are responsible for have the data they need, when they need it. The con is a lot more code needs to be written to simply get your data; you can’t just reach out and touch it on a Singletons’ public property. The pro’s are the TDD guys no longer get irritated, and PureMVC is already setup for the formalized process of getting your data. Again, it really comes down to the scope of your project, and how much you hate Singletons.
As always, the debates get really really subjective. Once you start talking about a single project, things get a lot clearer. For example, if I were doing a 1 page Flex app (yes, they exist), I wouldn’t use either of the above frameworks… I might not even use MVCS. Others however, cannot live without their framework of choice, and they are actually very productive using it. So… who’s right? No one because you can make a lot of good points in favor of one particular approach. Regardless you CAN get a list of pro/con bullet points and use a weighted approach; aka more dots in the pro side win assuming each dot is weighted the same.
Regardless, I still think Cairngorm needs a formalized Mediator; whether this be a convention, a View, or amalgamation of the UM extensions.