You can’t go too long talking about Flex without also talking about Cairngorm. Cairngorm is a micro-architecture and lightweight, yet prescriptive framework. In English, it’s a set of classes and conventions you use to make large applications in Flex. It’s usually the main framework most bigger companies use when doing Flex work. I say most loosely because there is always the possibility of the loudest minority syndrome. While it may be lightweight, it certainly expects a lot of developer foreknowledge & experience at the get go.
Cairngorm is meant for large teams working on large projects. Does that exclude it from small teams and small projects? No. Is it worth it? Depends on the scope of your project and less so on the amount of people on your team. There is nothing inherently wrong with 1 person coding Cairngorm as far as I’m concerned. It is made with the multi-developer project in mind and is suited for 1 person as well. However, if you are working on disposable software such as a demo, prototype, informal test case, or even a simple form, to me it’s not appropriate. The Pragmatic Programmer has something they call Tracer Bullets, which can be dangerously similar to a demo; you are creating an app for upper management to see. The temptation is to use the demo as the product. This happens more often than people care to admit, so… when in doubt, use Cairngorm to CYA. Steven Webster, one of the creators, has his take as well as when to not use Cairngorm.
Getting back to the requirements, you have to appreciate OOP, mainly, the encapsulation aspect. OOP typically suggests to make your code black-box routines; you put something in and get a result out without knowing the details. One class shouldn’t know how another one works without following rules and patterns that justify it and keep it under control. If you don’t recognize the reasons behind encapsulation, Cairngorm won’t make much sense.
Secondly, Cairngorm uses a lot of design patterns. Design patterns are a series of engineering theories that have proven themselves useful and predictable in their application in the real-world. They’ve then been adopted to the software engineering world and have helped a lot. Some are built into the programming languages themselves, such as ActionScript, whereas others can be developed by the programmer; some can exist in both. The keyword here is they are theories, and like all scientific theory, they can be proven empirically true time and time again, but never become fact. In my opinion, if they did, the software industry wouldn’t be as f’d up as it is right now. If you don’t recognize the need for patterns, or find their usage in large numbers tedious, you won’t like Cairngorm nor understand it’s value.
Third, Cairngorm is a good, solid platform for a LOT of code. When I say a lot, mean Enterprise level projects where hundred of thousands to millions of lines of code are normal. A lot of rules breakdown at large numbers; Space-time inside a black hole for example and search algorithms with regard precision vs. recall. Google’s recall ability is what made it so successful [Ambient Findability]. If you aren’t going to write a lot of code (not vs. don’t plan to; 2 different things), and your application is extremely small in scale, you won’t like Cairngorm because writing a lot of the setup code for Cairngorm will feel repetitive and pointless; you’re writing flexibility you’ll never use.
Fourth, which goes along with the third point, Cairngorm is setup for large teams. I’m not really sure what RAD development means, but I do know it’s spoken in tandem by managers with “a bunch of developers working on the same thing at the same time”. Cairngorm facilitates this in that the various parts that make up your application can be worked on by different people. One or more can work on the View’s, others on the use cases via creating Events & Commands, and yet others on testing their back-end services via Business Delegates; or multiple people on different classes therein. In the early days of Flash development, I had a hell of a time figuring who could work on what, and when. On larger projects where you have more resources, it’s now easy to find a spot for someone to work in tandem with others on the team. Although I am not a big proponent of large teams, I still like Cairngorm. If you are the sole developer… well, you’ll just have more code to write than you already do. If you can’t open source what you are working on to get help, you may see Cairngorm as more effort than it’s worth since you are the only dev. This assumes of course you have your own methodology.
Cairngorm, in a nutshell, provides a nice Model View Controller framework solution for allowing mid-size to large teams to write code collaboratively, where the framework scales with the size of the project if used correctly.
So does Joe Berkovitz’s MVCS.
Now might be a good time to go read Joe’s article if some of the above points turned you off from Cairngorm. If they didn’t, cool, go read to see Joe’s somewhat simplified framework, and gain context for other solutions beyond the Cairngorm / ARP / Fast way of doing things. This blog post can wait longer than I can.
Done? Pimp! Notice any similarities? A lot, huh? This blog entry sounding like I’m writing leading prose? I’m honestly not trying to, but when I read Joe’s article, to me, I found an extreme amount of commonalities. Joe’s been doing this stuff for over 30 years. I’ve barely done 6. The difference between Joe and I beyond the experience difference, however, is that I fail to see how you can develop anything without Cairngorm that is an application. If it’s a demo / prototype, fine. If it’s a single form, fine. A widget, fine. A 2 month throwaway project or something strictly written for a presentation, fine.
…anything more? Why not start right from the beginning? Is it really that bad to dive right in?
Unfortunately, it’s not that cut and dry. While it’d be nice if everything were measured in 2 weeks, 2 months, and 2 years development cycles, they aren’t, and there is a ton of in between, hence the confusion on when to implement a framework like JB’s MVCS, Cairngorm, ARP, and/or others, parts of frameworks, etc as well as when to do so. A variety of facets go into determining these things, way beyond a developers reactions to the 4 Cairngorm expectations I listed up top.
If there is one thing I’ve learned my short stint in this industry, it’s that you never stop learning, and plateau’s are merely brief respites that are really temporary purgatories between your next large climb. Once you realize a new concept, you level up, assign your new skill points to various personal skills, and start heading for the next level. You then realize how much you really don’t know. Every time I go to a conference, I meet smart developers, and wonder how I even survive in this industry with so many smart engineers.
So, hopefully some of the following confusions & frustrations Joe and others can comment on and give context so I can learn yet more.
Before I rant (I already did?), I want to give context as to why I’m doing this. First, someone I respect said they respected Joe’s viewpoints in his article and really identify with them in terms of doing their real world development. After reading even just other bloggers’ comments that linked to the article, this kind of floored me because of previous expectations. Second, I’ve gone through blood, sweat, and tears to get to the understandings and appreciations I have now for various programming and design pattern concepts. For someone to offer an alternative approach who has a lot of clout… well, it certainly was a how did I get here moment. Third, Leif Wells wrote an entry going over Cairngorm, and some of the typical resistance you may run into. In describing the benefits, pro’s and con’s, it helped give me context to how team leaders view use of frameworks as well as Cairngorm’s public perception to others. His entry really made me think about if there truly is a line when it’s “too much”.
Let’s touch on the first 30,000ft view point of Joe’s article. All 9 pages have one common theme; respect of good programming practices. Frameworks cannot exist without these; if they do, you shouldn’t be using them. They say wisdom of crowds can also be the mob insanity. To me, decades of smart engineers all agreeing through various blogs, books, forums, and scholastic disciplines about programming concepts being valuable as well as being implemented into real-world languages is enough for me. Like Descartes, I trust collected history of human experiences, ecspecially engineers. The great thing about programmers is that they are quick to point out there is an exception to ever rule. Therefore, even though we can all agree Object Oriented Programming has done a lot of wonderful things for this industry… JSFL in Flash doesn’t have classes for a reason. Procedural programming has a lot of valid offerings. The key here is that programming concepts, once learned, are a lot like language. Once you learn Literature (English as it’s called here in the US), you then get your poetic license. You can break the rules when writing because you know why you are breaking the rule; you are breaking it with impunity, intent, and have a desired effect. The same for programming. It’s okay to violate encapsulation if you have a good reason for doing so. It’s okay to use convention in place of stringent language features.
Bottom line, to me, the crux of Joe’s article is that he espouses good programming practices. If you do too, inevitably your code will be good, and more easy to scale. Use what you need, leave out what you don’t.
Let’s look at the similarities. Cairngorm has a model, a view, and a controller. JB’s MVCS has a model, a view, a controller, and a service. Cairngorm has a ServiceLocator, but that is merely for getting a reference to the service via a string name, keeping in centralized in case you change a CFC’s name server-side, or your Java FrontController moves to another server. JB’s MVCS Service, then, is more like Cairngorm’s Business Delegate’s, Delegates for short. Both invoke “server-side stuff”. Both create asynchronous operations, like making an HTTP request, calling a web service, making a Flash Remoting call, or even reading a local config file. Delegates get the locations of these things from the ServiceLocator, but inevitably “knows what they are”, and creates them. My Flash Lite 2 project, these are just a LoadVars. In my work project with Flex 2 and Java, these are HTTPRequests; about the same thing. Flash asks the server for JSON; Flex asks the server for JSON. It could be an XML request, a WebService, whatever. To me, these could be perceived as Operations. JB’s Services create Operations that make calls to the server as well. Both get and parse the data.
Key point here, namely page 5 of 9, last paragraph. He makes a good point about the client side ValueObject’s (which both frameworks have), specifically, about optimizing client-side versions. I agree. One of the most challenging things I find in some of these database driven projects is mediating the lingo between me and the server-side developer. Sometimes, a project can go on for so long, I become unfamiliar with all of the back-end database table names, and DAO objects. Sometimes, the server-side dude’s expectations are of me that the client should match the back-end. This is idealistic, and unwieldy. I’ll usually “translate” back-end business-logic-translated-for-the-back-end-developers-desire-to-have-a-relational-data-scheme to something more reader friendly on the front end. Yes, we both have PersonVO’s with an ID, firstName, and lastName properties. But things like PersonPatientCrossRefVO’s, and various other meshes of value objects that are either base classes, representing a database has-a table basically, or just some back-end concept that has absolutely no relevance to my front end GUI, but has some ID I need to get data… I have to handle these things. You might not want to take a shower and wear a suit, by you do so to the interview to get a job. So, while the panacea for years for me was to have my server-side and client side ValueObjects be the exact same… this was doomed to never happen. Some stuff on the server I don’t need to know about… just enough to get an ID I need to “barter” with them to give me the data I need. The same holds true for me. A lot of my optimized VO’s, or neat Collections have nothing to do with the back-end, and are merely there to make it easier for me to make a good looking, responsive, and easily maintainable GUI that works well with data. Optimized bindings, organized lists, etc. In my blind rush to get everything to match, I learned that Remoting, in the end, was merely a more efficient client to server communication technology. It took a large project for me to see my folly. Smaller projects? Maybe still valid.
It also implies, too, that Factories won’t go away. Neither Cairngorm, nor JB’s MVCS technically have the Factory pattern, but I use it in every single project I do now. Typically this is “throw some XML in, get a ValueObject out”, or JSON, and vice-versa. These are used in Cairngorm’s Delegates, or JB’s MVCS Services. Having a Factory create a nice client side version of our VO’s is very useful, encapsulated, and you end up with easier to read Delegate / Service classes.
I disagree with page 8 of 9 where it talks about Service objects passing data to the View. View’s should get their data in 2 ways; either through binding to a ModelLocator, or better yet, passed in via a parent. Joe does write about this. However, a View knowing status of a service operation is a valid need. I’ve written my own Cairngorm modifications just to facilitate this. My way was invented when I brainstormed with my team (Nahuel Foronda, Tom Link, and John Yanarella). A View has a callback it passes into the event it emits for Commands. These Commands then call these callbacks when they are “done”. It passes back Callbacks, which are like events, but are strictly there for context since I personally was uncomfortable with the idea of the same Event class playing double-duty. Either way, in Cairngorm, setting Model data is it’s sole duty. There is a reason for this: You’re back-end can change from XML to JSON, and your Commands don’t change. In JB’s MVCS, you’d have to change the same services class.
Is this bad? With few developers, no. Changing 1 class, or 1 bigger class is the same to me; just quicker to do the former via scanning. In a team environment, that won’t, fly, though. It’s pretty easy for me to have a Delegate in Cairngorm throw back a fake JSON object, and the rest of my team can continue working, even with the use cases (Commands). Additionally, while Command classes become significantly easier to read, for smaller projects, you’ll quickly wonder why you are writing 40 lines of code in a new class file that effectively do only 1 thing: set some data on the ModelLocator.
JB’s MVCS has the nice benefit here of a View knowing the “status” of a call. In Cairngorm, your default knowledge is “I emit an event, and go about my business”. Usually, Flex devs will set their RemoteObject calls to show the busy cursor. So, Flex apps work a lot like web apps in that a background process goes off and the user can continue working. A lot of times, this can be dangerous. If the user clicks save on the form, and assumes the data truly is saved, closes their browser and leaves, that’s a bad thing. You need to give confirmation, and other times, you don’t need confirmation, but you need to lock the GUI. There are various non-Cairngorm ways of remedying this challenge. State variables in ModelLocator that the Command can set or my callback approach are two. JB’s MVCS doesn’t have this problem. The Service can set all kinds of variables in the Controller which the View can access and/or bind to to know the “status”. To me, that’s a nice way to say “state variables”. In the end, your View is not built to a VO, but a few state variables in the Controller. I hate state variables. They are a bitch to manage on larger projects. Regardless, so far, my Event callbacks at least allow my View to know when things are “done”. I cannot for example show a progress bar for uploading a file easily without breaking the spirit of Cairngorm, whereas in JB’s MVCS, it’s easy and legit.
If you look at the first bullet on page 8 of 9 about the Controller having functions that a View can call being a lot easier than dispatching Events to run Commands in Cairngorm, he doesn’t say Cairngorm, but he implies it. Yes, it’s a pain in the neck. By why is it better? Parameter order. A function in ActionScript 3 has a strict order of parameters. These cannot change. If they do, you need to change all View’s that use the functions. Parameter View typically changes for the same reasons you’d need to change a property on an event. So, this is a mild benefit here that shouldn’t be underestimated.
It is kind of frustrating, though, managing Event classes in Cairngorm. Some Events have nothing to do with Cairngorm, like flash.events.MouseEvent. Now, luckily, that’s intrinsic. But, your custom ones need to reside somewhere in your folder structure either in the same package as the Cairngorm ones, or not. I vote for not, but some people like re-use of Event classes.
On page 9, he hits the interfaces questions, which are really good gut feeling metrics which I really agree with. Another really simple one to add: If others are going to use your code after you, use an interface. That way, they can’t whine about your inheritance tree, only your method requirements which is way more subjective. The fact that they can, by rules, play in your code with their code is much better than having to extend your code to play in your code.
That’s why Cairngorm 2.0 to 2.1 was half a PR move; it made all the Cairngorm hackers like me happy! I could use my own modifications, and yet still be officially using Cairngorm 2.1 on a project.
Additionally, on Singleton metrics, his first bullet point about asking yourself “could there ever be more than one of these, in this project’s lifetime?”. The exact same argument should be used for bindings vs. public getter / setters. Joe mentions this too, about having a parent set data on the child vs. having the child bind. It might not be apparent why you’d do this when binding is great. Beyond Joe’s reasons, debugging bindings is the most painful experience since a lot goes on under the hood when data changes. It’s easier to put debugging statements inside setter functions to recognize what really is getting set, and by whom. It also makes your View’s, like Joe says, flexible.
So, as you can see, Cairngorm and JB’s MVCS have a lot in common. A lot of Joe’s concepts are heavily based on good programming practices. I’m not going to say that Cairngorm allows you to be a dumb programmer, but following the rules, you can have a variety of skill sets on a project, and still be very productive getting real, useful code out of the team. The Delegate code, for example, could be nasty, but at least it gives the data to the Command correctly, and later can be re-factored. I suppose one could use the same argument about a Service object, but again, they do 3 things, not 2, (get data, parse data, set model) thus open the doors for more trouble.
To recap the similarities & differences, both have View’s, and agree that View’s should bind to a global Model of some sort, typically a Singleton using Flex’ built in data-binding. Cairngorm doesn’t explicitly state it, but having parents set data on View’s is more reusable like Joe says, for both. Both have a global singleton Model class of some sort. Both advocate making more than one if the class gets too big. Both respect the MVC approach of having View’s ask the Controller to change data on the Model, even though they have a reference to the Model to display data in it. JB’s MVCS has a Controller to do “stuff”. Cairngorm’s is done in Command classes, JB’s MVCS in the Controller class. I still haven’t figured out how you make the Controller class scale as opposed to Cairngorm Commands; when I used the Controller class in Flash, that thing got huge after awhile (aka a bunch of functions on _root). Cairngorm Commands set data on the Model and Business Delegates to get the data and parse it back for the Command which makes them. In JB’s MVCS, Services create Operations which do all 3, and can return that data directly to the View. Cairngorm does not have a standard way of doing this; it assumes that Views’ binding to a piece of data on the ModelLocator will have their data-bindings fired, which does work. Calling the Controller in JB’s MVCS is easy; you call a method on the Controller singleton class. In Cairngorm, you make an Event and dispatch it via the CairngormEventDispatcher singleton class. Neither proposes “return values”.
Hopefully reading Joe’s article will do a few things. First, it should give you an understanding that regardless of what framework you look at, good programming practices are paramount. Second, there are simpler frameworks than Cairngorm. Third, you can understand more about Cairngorm now that you have something to compare it against.
Me personally? I’m sticking with Cairngorm. I don’t see how the Controller in JB’s MVCS can scale, I don’t like being tied to parameter order in Controller functions, and I dislike the triple duty Service objects have after learning time and time again the benefit of using Delgates as a shield to changing middle-tier requirements. Regardless, if someone was using either framework on a project, I’d immediately know “how the app was built” which is something that shouldn’t be underestimated. There is nothing cooler going to a random client who needs Flex 2 help with an existing app, and they go “We used Cairngorm”. I immediately know how the app is built and can dive right in assuming they implemented Cairngorm correctly which is hard to screw up if you read the docs or hit up Flexcoders to ask if you are on the right track (or blog it).