Accessibility

Table of Contents

Developing Flex RIAs with Cairngorm microarchitecture – Part 6: Rapid and consistent development with Cairngorm and Flex

Cairngorm architecture review

To start an end-to-end review of the Cairngorm architecture, remember that Cairngorm is designed to facilitate a rapport between man and machine, listening to what the user wants, ensuring that the user gets what he or she wants, and then communicating that back to the user.

The Front Controller listens for user gestures

The user is in charge of the conversation. Your rich Internet application must awaits some indication from the user to know what to do. These indications—pressing buttons, dragging and dropping icons, double-clicking rows or submitting forms—are all called "user gestures."

Cairngorm translates these user gestures into Cairngorm events. Whenever there is a click, press, drag, drop, or submission of any event that represents a user demand, you can broadcast the event by using either the built in dispatch() method or by using CairngormEventDispatcher. The event broadcast is the beginning of the Cairngorm conversation.

The Front Controller pattern is the sole listener to Cairngorm events. By centralizing the handling of events, the Front Controller assumes responsibility for meeting the user's demands.

However, the Front Controller doesn't do the work; it's a manager, not a worker. The Front Controller instead maintains a list of "who does what," a list of commands that are best suited to responding to particular events.

Commands do all the work

Once the Front Controller recognizes an event for which it has a command on the payroll, as it were, it tells that command to execute. The Front Controller tells each and every command what to do in a consistent manner: the Front Controller calls the execute() method on the command and the command does its specific work.

Delegate server-side business logic to Business Delegates

Some commands require the server to perform a duty. In a rich Internet application, some business logic executes on the client side. More often than not, however, you'll want to shift some of the responsibility for business logic to the server.

Commands don't care about how something gets done; they just care that it gets done. Commands prefer to delegate the responsibility for server-side business logic to another class. There is a good chance, after all, that several commands that are trying to achieve distinct goals of their own will all require the same service for different things. What's more, for all the command knows, the business logic hasn't even been written on the server yet. Maybe the command is simply calling a dummy Business Delegate class, where the server-side infrastructure does not yet exist, but the Business Delegate offers an interface that will exist in the future.

So whenever you have business logic, put it into a Business Delegate class so that your commands can invoke methods on it.

The Business Delegate finds services with the Service Locator

The Business Delegate provides a seamless interface between commands and any services on the server. These services may be Java services, LiveCycle Data Services, ColdFusion Components (CFCs), web services, or simple HTTP services. The Business Delegate treats these services just the same, invoking them when the command asks and handing results to the command immediately when they become available.

However, the implementation details of these services—the names of the Java classes or CFCs, destinations, location of WSDL files, or the URLs for HTTP services—are all encapsulated into a shared repository of services, called the Service Locator.

The Service Locator is a single directory of all services that your rich Internet application requires. Because only the Business Delegate has responsibility for calling services, only the Business Delegate uses the Service Locator to locate services by name (caring nothing of their implementation) before invoking these services and handing the results to the Command classes.

Remember, any Command classes that assume the responsibility of responding to service calls and taking the returned data from the Business Delegate must do so by implementing the IResponder interface. In this way, the Business Delegate knows that the command will have a result() method to handle all results and a fault() method to handle any errors.

Transfer data as Value Objects

What happens to the data that is passed between client and server, and held on the client? Cairngorm insists that you treat data with a little respect, encapsulating it in Value Objects (also known as Data Transfer Objects) that describe what the data is in business terms ("it's an Order") rather than in technical terms ("it's an ArrayList of Objects containing a String and a Number").

Store state in the Model Locator and let the model notify the view

Finally, your application must be able to communicate back to the user. In Cairngorm, the Model Locator offers a pattern to store state, whether for the entire application, or part of the application. Developers have the option to have one or more models in their application to manage client-side state. Though Cairngorm does not prescribe how to implement the user experience with MXML and ActionScript, it does insist that anywhere the view is dynamic that the data for this view uses data binding to a Model Locator implementation.

Client-side state held within the Model Locator should be stored as Value Objects. When your Command classes ask the Business Delegate to call some server-side business logic on your user's behalf, they implement the IResponder interface and receive either Value Objects or collections of Value Objects in the result() method.

The very last part of the conversation in a Cairngorm application results in the command updating the Model Locator with any new state represented by these Value Objects. With the Model Locator using data binding to notify the view, the user interface updates to display any new data and completes the conversation with the user.