topleft
topright
Why Drive When You Can Fly? Print E-mail
Monday, 07 May 2007
"Bernard of Chartres used to say that we are like dwarfs on the shoulders of giants, so that we can see more than they, and things at a greater distance, not by virtue of any sharpness of sight on our part, or any physical distinction, but because we are carried high and raised up by their giant size."
-- John of Salsbury's Metalogicon, (1159 AD)

"I can see for miles and miles."
-- The Who

Software developers are creative people. And, I believe, it is this very aspect of our nature that causes us to write our best (and worst) code. It often helps us to 'think out of the box'; to come up with clever solutions to hard problems that are not obvious. Unfortunately, it also causes us to occasionally 'reinvent the wheel'; to waste time coming up with new answers to already well-solved problems.

For the last few years, I've been architecting and/or building large-scale enterprise applications in Flex. Where I had anything to say about the architecture, I have chosen or advocated Cairngorm every single time. The authors refer to their work as a 'microarchitecture'. It is a group of classes adapted from design patterns familiar to the J2EE development community.

Coming from an enterprise Java background where design patterns rule the day, yet having made a big ball of spaghetti with my first Flex app despite all that, I was pleased beyond words to discover a framework for developing rich clients that let me simply focus on the business at hand. Once the 'Cairngorm way' was understood, then it was possible to really get on with it.

However, I noticed a somewhat disturbing trend. On more than one occasion, I showed up at the client's site, created a Cairngorm-based prototype - not throwaway code, but intended to be 'inflated' by their developers into the actual production application, only to come back or hear six months later that they'd thrown it all away and started from scratch. Not because I left them with bad code, but because they were not able to grasp the 'Cairngorm way', and all applications are, of course, due to ship yesterday. With pressure to deliver, often brute force rules the hour and overshadows good sense. No time to learn, we've got to ship!

Needless to say, this leads to the same problem I had with my first Flex app. Maintainability and scalability are right out. You can always burn down and rebuild later, right? Having been in that spot myself, I may not sympathize, but I do empathize.

Also, personally, I tired of the ongoing releases and all that keeping up entailed. First the package was 'com.iterationtwo.cairngorm', then it was 'org.nevis.cairngorm', now it's 'com.adobe.cairngorm'. First the ModelLocator was simply a marker interface reminding us to make a class with a bunch of static members that we could access from anywhere. Now it's a Singleton. First we were advised to use the ViewHelpers and ViewLocator, but no firm guidelines about just how much or what code should go into them. Is one ViewHelper per view component really necessary? What if you need multiple instances of the same ViewHelper? Then word was, maybe we shouldn't rely on them so heavily. Another release made some dependencies on Flex Data Services, and now, realizing that everyone might not use FDS, those bits have been extracted out to something called 'Cairngorm Enterprise'.

This post is definitely not meant to be a Cairngorm-bashing session, but rather to make clear some of my motivations for creating PureMVC. I realize there's already a wheel out there, but damn it, this is the new millenium, and I want a Hovercraft.

So, where it comes to standing on the backs of Giants, I must tip my propeller beanie and give props to the aforementioned esteemed individuals and their admirable work. It was only from the perspective that Cairngorm afforded with all its strengths and weaknesses that I could see this solution off in the distance, beckoning, asking to be built.

I wanted something that helped achieve the separation of coding interests that the Model-View-Controller 'meta-pattern' suggests in a clearer fashion. MVC has been around for sometime, surviving the rise and fall of many platforms, languages and environments. Yet, unlike design patterns that state clearly the roles, responsibilities and collaborations of the classes used to solve their problems, there is no specific prescription for implementing MVC. So that much I had to devise myself after quite a bit of survey of the prior art. See my previous posts regarding this process.

As artsy and creative as I'd like to think I am, in reality, I'm a pretty literal-minded guy. I like things to be straightforward and understandable. So the Core actors of the PureMVC framework are, predictably: Model, View, and Controller. They are all Singletons whose primary responsibilities are to cache instances of the classes that do the actual work of their respective realms.

The other classes of the framework all stem directly from the fabled 'Gang of Four' book; Design Patterns: Elements of Reusable Object-Oriented Software. Everytime I found myself dreaming up a solution and trying to think of a name for it, I realized I was off track, and returned once again to this wonderously timeless and relevant tome. From the shoulders of giants indeed. Though the examples are variously in C++ or Smalltalk (the software equivalent of Latin), its prescience cannot be understated. I wager it will be as applicable next century as it is today. And a very positive side-effect is that if you want to understand the PureMVC classes, buy this book. I could never hope to deliver a more elegant and thorough description.

Of course that does not obviate the need for me to document and you'll find plenty of that and more to come. Elsewhere on this site, you'll discover detailed API documentation as well as UML diagrams illustrating the high-level relationships of the framework classes. Go have a peek. If you have the Gang of Four book, crack it open and refer to it as you look around.

A brief overview:

The Model caches Proxys, which represent and control our interaction with data objects, whether they be local, and therefore synchronously accessable, or remote and consequently accessed with an asynchronous idiom.

The View caches Mediators, which listen to and manipulate the visual components in our application.

The Controller instantiates and executes Commands at the behest of other parts of the app. Commands house our client-side 'business logic' choreographing the more complicated high-level operations such as application startup.

From prior posts to this blog, you'll be aware that another goal of PureMVC was to eschew dependence on Flex or Flash classes, something that Cairngorm is deeply tied to. The idea was that if I played my cards right, we might wind up with a framework usable by developers targeting Tamarin (the Mozilla Foundation's integration project which will yield next year's JavaScript, based upon ActionScript 3). That's yet to be seen, but I do have hope. PureMVC relies only upon the ActionScript native data types.

As a result, I needed a facility for event-driven communications between PureMVC classes that did not use flash.events.Event. The result was Observer and Notification.

Notifications are very similar to Events. A key difference is that they are not tied to the display hierarchy as Events are. The Flash Event model follows the 'Chain of Responsibility' pattern. If the parent of the component that dispatches the event doesn't handle it, (and the event is set to 'bubble') then the parent's parent gets a chance to, and so forth. Notifications are not meant as a replacement for Events. In fact, in a Flash/Flex/Apollo app, Mediators will always place event listeners on the view components they steward. In fact a visual component need never be aware that it is part of a PureMVC application, making porting to PureMVC (or away from it for that matter) a reasonably straightforward process, and yeilding view components that are easily reusable in other contexts.

PureMVC Observers and Notifications resemble a 'Publish/Subscribe' pattern whereby any class can be registered as an Observer that will be notified when a given Notification is broadcast. For various technical reasons the responsibility of maintaining the Observer lists and broadcasting the Notifications falls upon the View.

But you really need not be concerned with exactly where all of these responsibilites fall because of the Facade. Another pattern well described in Design Patterns, the Singleton Facade class gives our application a single touch point for interacting with the Core actors. We never have to import, sublcass, or work directly with the Model, View, or Controller classes. Instead, we create a Facade, which in turn, instantiates and caches references to the Core actors, providing access to all their functionality by composition.

And thats it. Model and Proxies, View and Mediators, Controller and Commands. Observers and Notification allowing them all to talk to each other in a loosely coupled way. And finally, the Facade lets us look think of the whole thing as a black box with a simple API.

You need only subclass the Facade, write Proxies, Mediators & Commands, and you can use everything else out-of-box. However if you want to subclass or replace any of the Core actors, you may easily do so, and the API reference gives explicit instructions about what to consider if you decide to. All the non-public members of these classes are marked protected and not private with this in mind. Also, interfaces are defined for and used in the method signatures of all classes in the framework so that you may subclass or compose your way to your solution as you see fit.

The goal was MVC separation and greater simplicity at implementation-time and it has been attained. I have a fairly non-trivial Apollo application teetering on the edge of deliverability that will be posted for your perusal very soon. It interacts with a remote http service, maintains a number of XML databases on the user's filesystem, sports a rich interaction model including drag-and-drop of data between components, easy handling of popups, and in-place editing of data in tables, trees and lists. It orchestrates a complex startup routine that includes restoring the window position and or maximized state as well as application of a custom color scheme from the database, and coordinated initialization of the Model and the View - all prior to presenting the interface to the user, which happens with a swift animated presentation. And it all happens lightning-quick.

Put on your rocket-boots, Elroy.

-=Cliff>

Chris Luebcke said...

Very exciting, man. But what will really help me grok it all is seeing the code for the app you built with it :

  

Anonymous said...

Interesting work.
It would be nice to see a diagram of the complete stack in action - say from clicking on a button over asking the server for some data to updating the ui.

 
 
George said...

Hi Cliff,

Chris L. told me about pureMVC and I am very impressed with the framework and all the effort you've put into it. I will definitely be strongly considering using it for my future projects.

I am curious about one thing, however. What is your motivation behind dedicating so much effort to an open source framework? Do you plan to open it up to more developers in the future, and in the future are you planning on charging a licensing fee for the framework or parts of it?

 
 
Cliff Hall said...
George,

My motivation for creating PureMVC was to offer a solution with a clear scope that would not creep, and hopefully be well planned enough not to require the continuous changes that are part and parcel with the other frameworks out there.

I wanted this primarily for myself, so that I did not have to leave clients with solutions based on a framework that they would later have to upgrade themselves or pay someone to do for them. That casts me in a bad light as a solution provider.

I wanted something that offered scalability, maintainability, and was easy to understand and implement a full-featured RIA with.

As to open-sourcing or bringing in other developers, no, I really have no intent for that. The scope was clearly defined, and when it was met, the creepy-feature creature was shot in the head. I have no intentions for an 'Enterprise' version. This is the version I suggest for the enterprise. I've been writing apps for the enterprise long enough to know what's needed in an MVC framework. That is: only what is required to build a loosely coupled system which helps you to keep straight in your mind and your code what belongs in the model, what belongs in the view, and what belongs in the controller. Period.

What about workflow and caching and blah, blah, blah, you ask?

Of course there will be PureMVC-based solutions to common problems which will be developed and posted from time to time, but they will not affect the framework itself in any way.

If I'm lucky and the hard work put in thus far pays off, PureMVC itself will remain at 1.0 forever. Of course, nothing's ever perfect and I'm sure something will turn up that requires a minor maintenance release, but I do not intend to add or subtract anything from what is there now.

As for fees, there will never be a charge for using PureMVC in your application.


Your reuse is governed by the Creative Commons Attribution 3.0 United States License, included in the source code zipfile.

-=Cliff>

 
 
Cliff Hall said...

And, to answer anon's question: the 50,000 foot view is on its way, for sure.

This project is has taken so long not only because I've been working out the right balance of things but also because that work is squeezed into the spaces between flying all over the place training people on Flex and working on apps for clients.

I have a 13 hour flight across the country tommorow which is perfect for this sort of thing if there's enough room to use the laptop in the seat I'm in :)

Unlike some other frameworks out there, I don't intend to leave it up to the community to do my documentation for me. It seems to me that task should fall on the shoulders of the framework architect.

-=Cliff>

 
 
Cliff Hall said...

A brief update on the 50,000 foot view, to those following this thread, I did get some work done on the plane. Have a look at:

PureMVC.org->Diagrams->Conceptual

This should give you a good idea what's going on at a high level.

Next up: Best Practices for Implmenting your PureMVC-based Application.

-=Cliff>

Delicious
Technorati
Reddit
Furl it!
NewsVine
YahooMyWeb
Stumble
blogmarks
Digg
co.mments
connotea
Last Updated ( Saturday, 14 July 2007 )
 
Copyright © 2006-2008 Futurescale, Inc.