I have had Robotlegs on my radar screen for months now, just didn’t have the time/brains to really check it out. I cut my Flex framework teeth on Cairngorm 2, which seems to be the framework non grata of all the current well-known Flex frameworks (Swiz, PureMVC, Robotlegs, etc.) However, at Joel Hooks‘ suggestion, I took a look at Cairngorm 3 (henceforth referred to as CG3), enough to do a presentation on it for a recent nerd conference. The presentation includes a demo app that I wrote using Cairngorm 3, which (currently) uses Parsley as it’s IoC container. That’s right, Cairngorm 3 presumes an IoC container, but does not specify one. This means that you can adapt the CG3 guidelines to your IoC of choice. This is only one of the many ways CG3 is different from CG2, with others being:
- No more locators, model or otherwise. Your model can be injected by the IoC or handled via events. For you Singleton haters, this is a biggie.
- A Presentation Model approach is prescribed, meaning your MXML components are ignorant of everything except an injected presentation model. The views events (clicks, drags, etc) call functions on the presentation model inline. The presentation model then raises the business events. This allows simple unit testing of the view logic in the presentation models.
- The Command Pattern is still in use in CG3, but commands are not mapped the same way. For CG3, your commands are mapped to events by your IoC. Parsley has a command pattern approach in the latest version that actually came from the CG3 beta. This approach uses metadata (like [Command] and [CommandResult]) to tell Parsley which event to map. Again, this results in highly testable command logic.
- CG3 includes a few peripheral libraries to handle common needs that are very nice. Things like Popups, navigation, validation, and the observer pattern are all included in libraries that are not dependent on using CG3 or anything, really. If you don’t intend to use CG3, it may be worth your while just to check out these swcs.
All in all, CG3 is a breath of fresh air for someone who has been using CG2. Cairngorm 2 is fine, and it’s certainly better than not using any framework, but the singletons always made me uneasy and, in some of our lazier moments, we ended up with hacks to get the job done. I feel that CG3 really supports a test-driven approach and Parsley is very nice and well-documented. It’s worth saying that I only know enough about Parsley to get it to work in the CG3-prescribed manner, and there seems to be much more to the framework.
Once I had a basic handle on CG3, Joel said he was interested in how CG3 could work with Robotlegs (henceforth referred to as RL). Also, after my presentation, a couple of folks wandered up and mentioned RL as well. So, when I got home, I ported the demo app to RL (it’s a branch of the github repo I link to above) so I could finally check it off my Nerd Bucket List.
First of all, Robotlegs is, like CG3, prescriptive in nature. It is there to help you wire up your dependencies and maintain loose coupling to create highly testable apps (right, all buzzwords out of the way in one sentence. Excellent) Like CG3, it presumes an IoC, but does not specify a particular one. The “default” implementation uses SwiftSuspenders (link?) but it allows anyone to use another IoC if they feel the need. I have heard rumblings of a Parsley implementation of RL, which I’d like to see. Also, the default implementation is more MVCS-ish than the default CG3 implementation. What the hell does that mean? Well, MVC is a broad brush and can be applied to many architectures. In my opinion, the CG3-Parsley approach uses the Presentation Model as the View, the Parsley IoC/Messaging framework for the controller and injected value objects for the model. The RL approach uses view mediators and views for the view, which reverses the dependency from CG3. The RL controller is very similar, but commands are mapped explicitly in the context to their events, rather than using metadata. The model is also value objects, but it’s handled differently. In CG3, the model is injected into commands and presentation models, then bound to the view. So, if a command changes a model object, it’s reflected in the presentation model, and the view is bound to that attribute on the presentation model. In RL, the command would raise an event to signify model changes, passing the changes as the event payload. The view mediator listens for the event, handles the event payload to update the view, again through data binding. (NOTE: You can handle the model this way in Parsley as well, using [MessageHandler] metadata tags, FYI)
It’s worth mentioning that when I did the RL port, I added a twist by using the very impressive as3-signals library from Robert Penner. Signals is an alternative to event handling in Flex, and I really like it. Check it out. Anyway, RL and Signals play very well together, but it means I wasn’t necessarily comparing apples-to-apples. Signals is not a requirement of using RL, at all, but the Twittersphere was raving about it and I can see why. The biggest con to using Signals with CG3 might be some of the peripheral CG3 libraries. For example, I think you’d end up writing more code to adapt things like the Navigation Library to Signals. The Navigation Library uses NavigationEvent to navigate between views, which would need to be adapted to Signals. Of course, I am of the opinion that, if you are going to use something like Signals, you should use it for ALL events and not mix the two eventing approaches. This is a philosophical issue that hasn’t had the chance (in my case) to be tested by pragmatism.
So, which framework do I like better? After a single demo application, it’s hard to make a firm choice. I really like the CG3 approach, and it’s only in beta. However, I also really like the Signals and RL integration, which I think makes eventing in Flex much easier to code and test. I am not that big a fan of the SwftSuspenders IoC context, as there doesn’t seem to be anyway to change parameters at runtime, which is something I use IoC to handle. An example is a service URL that would be different for test and production. I’d like to be able to change that in an XML file without having to rebuild my SWF. I asked about this on the Robotlegs forum, and was told that it’s a roll-your-own answer. On the other hand, Parsely offers the ability to create the context in MXML, actionscript, XML, or any mixture of the three. I like that. I think the winner could be a Parsley-RL-Signals implementation pulling in the peripheral CG3 libraries, which mixes everything I like into one delicious approach. MMMMMM.
Anyone have questions about the two frameworks that I didn’t cover? Hit the comments. Also, if anything I have said/presumed/implied here is flat out wrong, please correct me. The last thing I want to do is lead people (including myself) down the wrong path.
Related articles by Zemanta (well, some of them were by Zemanta, others by me)
- Cairngorm 3.0.2 release (blogs.adobe.com)
- Joel Hooks’ Robotlegs Image Gallery Example using the Presentation Model (I used this for my port to RL)
- Enterprise Development with Flex (oreilly.com) This book looks interesting, but they (disappointingly) stick to discussing CG2.
- The Flexible Configuration Options of Parsley (blogs.adobe.com)
- Eidiot’s Signals Async Testing Utility on Github (use this to test your signals)