Flex Architecture Fundamentals Part 3 : Designing the Flex application as a Model View Controller

This post belongs to a four part series :
Part 1 Rich Internet Application Server Architecture Basics
Part 2 Main Means Of Communication Between Flex And The Application Server
Part 3 Designing the Flex application as a Model View Controller
Part 4 Using Architecture frameworks

In the previous parts of this series, we've seen that a Flex client can be considered as the View layer of a RIA MVC-like architecture.
Among other things, this means that it has to be as independent as possible from the application server's implementation. Ideally, a Flex client should be able to switch from a service to the other as smoothly as possible. The only dependencies it needs to have is to the Service API, which, as we know, may return so-called Value Objects.

While Flex offers various ways to communicate with an application server, most of the time, for an enterprise application, the choice is easy : either a WebService object to communicate with SOAP WebServices, or a RemoteObject to communicate with any kind of service behind an AMF Gateway. This last solution provides great benefits both in terms of performance and development since it deals with ActionScript binary objects.

Today, we'll see how one can structure a Flex application to limit the coupling between the various layers of our application with the help of design patterns. Our goal is to apply common methodologies through best practices that favor code reuse, maintainability, legibility of code, and productivity. We won't discuss design pattern theories here, nor are we going to enter the details of their actual implementation in ActionScript. We're just here to try to grasp a picture of a Flex application architecture main concepts.



The Flex application architecture as a Model View Controller (and other related concepts)


Before I begin, I should probably warn you dear readers : while some of you (I'm lookin at you Java guys ;) ) are quite familiar with the concepts discussed here, others may find it overly complicated for no obvious reason. The goal of this post is not to tell how a Flex application should always be built, but rather to present common solutions to common problems and how to articulate them. However, with the use of code generators, you may find out that more classes does not necessarly mean more work. But that's for another post.

Now back to our business ;)

In the first part of this series, we've seen that the Flex application can be seen View layer of the RIA MVC. But the Flex application can itself be thought of as an MVC inside the web application MVC :




The View layer


The View layer of the Flex MVC mainly consists of your user interface which, most of the time, is described as a hierarchy of MXML components. The application's root component represents the top of the UIComponents hierarchy. It can be either an Application object (in the case of web Flex applications), or a WindowedApplication object (for AIR). In a Modular application, it can also be a Module object designed to be loaded in a container application.

Inside this hierarchy, communication is achieved through an implementation of the observer pattern : flash's Event mechanism. This allows communications while reducing dependencies, which is exactly what we need. Moreover, Flex provides an additional mechanism to easily update shared data between the views, which also relies on Events : DataBinding.

This way, our views are as independent as possible from the rest of the application. They only deal with what they need to. For example, you might see a BookForm, which lets a user update a Book object with a form. Our BookForm component will only have a reference to the currentlySelectedBook, a Book-typed property in our Model (a ValueObject). The user will click on a "Save" button, which will dispatch an UpdateBookEvent. The Controller will listen to this event, do what it has to do, and update the Model's currentlySelectedBook property accordingly. Since this property is linked by DataBinding to our BookForm, it will immediatly show the updated Book.


The Model layer


The Model layer is just supposed to store data, thus representing the state of the application. It has no logic, excepted maybe logic that is strictly related to data access. In its simpliest form, it's just a collection of properties declared inside the application's root tag. But this is not a good a idea because Model cannot belong to a view without becoming highly dependent to it.

So, quite often, it is implemented as a Singleton, because it is unique and might be accessed easily. Sometimes, it's scattered into several objects, and this Singleton is just a way to access these different parts. Among these objects, we find Value Objects. Just like the application server's, a Flex Value Object is a representation of a Database table record.

So we could, for example, encounter a Model that takes the form of a Singleton with some properties such as currentBook, typed Book (our Value Object), and bookList, typed ArrayCollection, which would, of course, consist of a list of Book objects.



The Controller layer


The Controller is responsible for the logic that takes place between the View and the Model. When the user interacts with the interface, the Controller is supposed to do something (update the Model, most of the time). Again, in its simpliest form, it's a list a methods in the application's root component. But this would result in the tightest coupling we can think of between the main View and the Controller. So we need to seperate them. This, again, can be achieved with events : the views simply dispatch events, the controller listens to them and acts accordingly.

The way the controller can handle these events and the corresponding actions can take different forms. But, most of the time, we use yet another pattern : the Command pattern. The controller becomes a FrontController that listens to user gesture events and delegate to objects named Commands what to do. A command encapsulate the action corresponding, most of the time, to a user gesture. This is extremely powerful since it allows to easily implement some complex mechanisms such as an "undo" gesture, macros, etc...

Sometimes, the Commands need not to (or not only to) update the model, but also to act in a way that could update the User Interface. For example, imagine a PopUp Window that prompts a user to confirm the deletion of a Book. The user confirms it, so the view dispatches a DeleteBookEvent, the DeleteBookCommand actually deletes the book, but through an asynchronous operation, such as a Service call.
We probably want to close the Deletetion Confirmation PopUp Window when it's done, or to update its text to tell the user that the operation was successful.

To do so, the Command needs a way to access the View layer. Of course, it cannot access it and cannot have any reference to any view since it would immediatly create a dependency between the two. So our Command will have to dispatch an Event. But how can our view know how to listen to this event? Well it can't, because, again, it would create a dependency. So we need to have in-between objects, sometimes called View Helpers, which will actually listen to events dispatched by the Controller Commands, and have a reference to the views to be able to update them.



The Business layer


One of the main tasks of these commands is to communicate with the application server to let it update the web application's Model, i.e. the DataBase. A command will then have to use a RPC component to let it call the actual Service method.

But we can easily imagine that the Service might change during the developement cycle. To improve the maintainability of our Flex application, we can use a Business Delegate which goal is to expose the API of the service. So, the Commands that handle the logic corresponding to a user gesture which goal is to eventually update the web application's Model will delegate this job to the Business Delegate.

RPC objects have the ability to designate so called Reponders to handle the response, or result if you want, of the Service call. If we've choosen to implement the Command pattern, chances are that these Commands will do the job.

Moreover, if the Service API can change, so can the way to communicate with it, i.e. our RPC component. Using a ServiceLocator, we can encapsulate the actual implementation of our RPC components.



Putting it all together


Now that we've seen each part of our application, we can imagine what an application that would implement all these techniques would look like.
First, a simple sketch to see the main connections

And then the whole thing, as we described it.

As you can see, it looks pretty complicated. But don't forget that many of these objects are pretty dumb. The FrontController does almost nothing more than associate events with commands. The Model is just a glorified list of properties. The BusinessDelegate is basically the result of a copy and paste of the Service API, etc...

But still, they role is very important because they're part of the architecture, which provide great benefits :

  • Most applications you can think of can fit into (at least part of) this scheme. When begining to work on a new, and maybe complex application, these reasonings can give you guidelines for your development. Once you know one, you know all of them. Also, you can read your colleagues work very quicky, and of course so can they read yours, because they know where to find what they're looking for. This means time saving. This means productivity.
  • These techniques are quite common in the software development world. If you don't all them, chances are that some of your friends/bosses/pets/whatever know at least some of them, even if they know nothing about Flex. That's especially true for Java developers, but not only.
  • In a complex application, that is subject to change, especially in a context of Agile development, these solutions are truly extremely powerful because they help iterative development. Don't underestimate them just because you've never encountered the problem they solve. Because you can be certain that one day you will. And you'd better be prepared. ;)
  • You don't have to use the full set of patterns. Truth is, sometimes, only a minority of them will really be useful during the development cycle. That may contradict what I've just said before, but of course it's true. However, you should know them to carefully select which one can be suitable for your application, and which one can not.
  • Frameworks are here to help you. They provide a ready to use implementation of most of these patterns, and can help you deal with them. Frankly, unless you're the next development rockstar, you probably cannot deal without them anyway. So why bother?
  • Code generators can also save you a lot - and I mean A LOT - of time. Since most application code can be written by following a predefined set of rules, they can help you dramatically increase your productivity. Of course, I'm partial here. But they are more and more generators these days. So don't just trust me : try one.

Of course, as you can probably guess, we've only scratched the surface here.

In the next part of this series, we'll talk about implentation, and of course, frameworks. Now that we know the basics, it will be a lot easier to understand them.



Additional References

The Command Pattern on Wikipedia
http://en.wikipedia.org/wiki/Command_pattern

Joe Rinehart on Responders
http://www.firemoss.com/blog/index.cfm?mode=entry&entry=6D96F27D-3048-55...

The Business Delegate in J2EE
http://java.sun.com/blueprints/corej2eepatterns/Patterns/BusinessDelegat...

Agile Development on Wikipedia
http://en.wikipedia.org/wiki/Agile_software_development

AttachmentSize
Business1.jpg46.38 KB
Business2.jpg65.81 KB
Controller1.jpg44.52 KB
Controller2.jpg29.21 KB
Model.jpg48.73 KB
MVC_in_MVC (Flowchart).jpg50.01 KB
ViewLayer.jpg76.56 KB
FlexArchitecture.jpg79.42 KB
FlexArchiFull.jpg128.1 KB

Anonymous on February 18th 2008

Very good and direct presentation of what MVC really is.

Anonymous on February 29th 2008

Enjoyed your clear explanation

Anonymous on April 26th 2008

Excellent job!

Collin (not verified) on December 10th 2008

This is one of the clearest explanations i've seen. Keep up the great work!

Anonymous (not verified) on March 30th 2009

Hey,
Hobi Good article,Thanks for it.Örgü
I did came across a simillar task recently. Örgü Modelleri
I have implemented it using PLSQL , I did reffered mine with this article,they have same logic. Örgü Teknikleri
Hope many other friends would have had a very simiilar case, very helpful. Sihir

Shameer Salim (not verified) on January 30th 2009

Excellent Presentation with effective diagrams :-) A recommendable resource for those who likes to dive deep into architecture

rdamon (not verified) on March 19th 2010

Thank you for that marvellous tutorial : well explained, not too fast, not too... and very rich in knowledge!

Congratulation that's on of the best tutorial I have ever saw, keep on the good work

Anonymous (not verified) on June 12th 2010

Congratulation that's on of the best tutorial I have ever saw, keep on the good work

Krishma (not verified) on July 06th 2011

Thanks for sharing your knowledge in such a nice manner, easy to read and understand and most importantly easy to retain that information also. I am very much able to make a clear picture of what happens exactly :))