Accessibility

Architecting Flex Applications

Christophe Coenraets

Adobe

After building a couple of initial "getting started" applications with Macromedia Flex, developers often experience a feeling of liberation: all of a sudden, the all-too-well-known limitations of HTML for building applications disappear, and it’s hard not to get excited by the new possibilities and opportunities that the Macromedia Flex Rich Internet Applications platform unleashes. As a developer, you can finally build real applications for the client tier. While leveraging the ubiquitous and real-time deployment model of the web, these applications are neither cluttered with page refreshes nor limited to a handful of user interface controls. Furthermore, they can expose rich user interface metaphors such as drag and drop, and even access a local data storage area to work in an occasionally-connected mode.

The bottom line is that Rich Internet Applications are... applications. This also means that they have the same requirements as any other application: stability, robustness, extensibility, and reusability.

So, after the initial excitement, the next logical question often in the developer's mind is: "What’s the right way to architect larger scale, real-life Flex applications?" The short answer is that there is no reason to abandon the proven software engineering methodologies and practices that have governed application development for years.

This article provides a more detailed answer to this question, and describes how to build large-scale Flex applications using sound design patterns, such as the model-view-controller (MVC) architecture, and best practices, such as loose coupling of application components.

Capturing the Application Requirements

Every application is designed to solve some kind of business problem, and usually the first step in the development life cycle is to gather the application requirements. In this article, I use Flex Store, one of the sample applications packaged with Flex, as a case study (see Figure 1). You don’t need to install Flex, the Flex Store sample app, or be familiar with the application to read this article.

The Flex Store application

(+) View Larger

Figure 1. The Flex Store application.

The Flex Store is a traditional shopping cart application. The initial requirements for the shopping cart application included:

Object-Oriented Design

After you have captured the application requirements, you design (in the object-oriented sense of the term) and implement your application in the same way you would using another object-oriented programming (OOP) language.You build a Flex application, like any other object-oriented application, by assembling classes. An important task at this stage of the development life cycle is to identify the classes in your system. In this process, it’s a good idea to embrace proven design patterns—such as the MVC architecture —to promote the overall maintainability of your application and the reusability of your classes. Using the MVC architecture, partition your system into three categories of classes:

Figure 2 shows a high-level UML class diagram for the Flex Store application. In this diagram, the Model classes are yellow, the View classes are green, and the controller classes are orange.

The UML class diagram for the Flex Store application

Figure 2. The UML class diagram for the Flex Store application.

One of the traditional advantages of application partitioning is that you avoid duplicating code and you increase the reusability of application components. For example, ThumbnailView and GridView provide two different ways to look at the same data without duplicating code in the Model logic. Similarly, the CartView class represents one way to display the contents of a shopping cart. You could easily create another view of the shopping cart data without duplicating the shopping cart Model logic.

Implementation

Using Flex, you can create the classes for your application using MXML, the Flex XML-based markup language, or Flash ActionScript 2.0. ActionScript 2.0 is a fully object-oriented and strongly typed programming language. It is compliant with the ECMA-262 standard and will be familiar to Java and C# developers.

You typically use MXML to implement the user interface classes in your application (View), and ActionScript to build the non-visual classes (Model and Controller). Many of the controller classes you need to build your applications are available by default in the Flex class library.

This combination of a tag-based language to create the user interface (View) and a traditional OOP language to create faceless classes (Model or Controller) has emerged as a popular programming model: The same combination exists in Java presentation-tier development between JSPs and JavaBeans. Microsoft Longhorn Markup Language, or XAML, is also based on the same model.

View Classes

ThumbnailView, GridView, ProductDetailView, ShoppingCartView, and CheckoutView are the main user interface classes in the application. They are all built in MXML and represent self-contained components of the application’s user interface.

Using Flex, you can create MXML classes from scratch, or by extending or aggregating existing components. The following example shows the source code for the CartView class. The name you specify for your MXML file defines the class name. For example, to create the CartView class, simply name the source file CartView.mxml.

1  <?xml version="1.0" encoding="utf-8"?>
2  <mx:Panel xmlns:mx="http://www.macromedia.com/2003/mxml" title="Shopping Cart">
3    <mx:Metadata>
4      [Event("checkout")]
5    </mx:Metadata>
6    <mx:Script>
7      var cartData: ShoppingCart;
8    </mx:Script>
9    <mx:NumberFormatter id="price" precision="2"/>
10    <mx:DataGrid id="dg"
11      dataProvider="{cartData.items}"
12      widthFlex="1" heightFlex="1">
13      <mx:columns>
14        <mx:Array>
15          <mx:DataGridColumn columnName="name" headerText="Name"/>
16          <mx:DataGridColumn columnName="qty"  headerText="Qty"/>
17          <mx:DataGridColumn columnName="price" headerText="Price"/>
18        </mx:Array>
19      </mx:columns>
20    </mx:DataGrid>
21    <mx:ControlBar>
22      <mx:Button label="Delete" click="cartData.removeItemAt(dg.selectedIndex);"/>
23      <mx:Button label="Checkout" click="dispatchEvent({type: 'checkout'})"/>
24      <mx:Label styleName="price" text="Total: ${price.format(cartData.total)}"/>
25    </mx:ControlBar>
26	</mx:Panel>

Note that the root node in the MXML file specifies the class you extend. In this case, CartView extends the Panel class (line 2).

CartView has a reference named cartData to a ShoppingCart object (line 8). ShoppingCart is a Model class that represents data in a shopping cart and that provides an API to manipulate the data. I present the source code for the ShoppingCart class in the following section.

The CartView data grid is bound to the shopping cart items in the Model object (line 12).

Model Classes

Catalog, Product, Order, and ShoppingCart represent the Model classes in the application. Because Model classes are faceless by nature, you typically implement them in Action Script.

The following example shows the source code for the ShoppingCart class. ShoppingCart encapsulates shopping cart data and provides an API to manipulate the data.

ShoppingCart.as

class ShoppingCart {
    var items : Array;
    var total : Number = 0;
    function ShoppingCart() {
        items=new Array();
    }
    function addItem(item : Object, qty : Number, index: Number) : Void {
        items.addItemAt(index, {id: item.id, name: item.name, price: item.price, qty: qty});
        total+=parseFloat(item.price)*qty;
    }
    function removeItemAt(index: Number) : Void {
        total-=parseFloat(items[index].price)*items[index].qty;
        items.removeItemAt(index);
    }
    function getTotal() : Number {
        return total;
    }
}

Controller Classes

Web service is a Controller component built into the Flex class library. It provides the plumbing to connect to web services. Another built-in Controller component implicitly used in the application is the Binding class, which sits between the View and the Model components: the Binding class automatically notifies the Views when relevant data changes in the Model component.

Assembling the Application

After implementing your initial components, you start putting the application together by assembling these components. In this case, Flex Store is the main class (the starting point) of the application. The Flex Store class is defined in MXML and aggregates the View components described in the “View Classes” section above.

The following snippet shows the skeleton for the Flex Store class.

flexstore.mxml

1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*">
3   <ShoppingCart id="cart"/>
4   <mx:WebService id="catalogWS" serviceName="FlexStoreCatalogWS">
5      <mx:operation name="getList"/>
6   </mx:WebService>
7   <mx:Model id="catalog">
8      {catalogWS.getList.result}
9   </mx:Model>
10  <mx:HBox>
11     <ThumbnailView id="thumbView"
12        label="Product Catalog"
13        dataObject="{catalog}"
14        change="selectedItem=event.target.selectedItem"/>
15     <mx:VBox widthFlex="1">
16        <ProductDetail id="productDetail"
17           productData="{selectedItem}" 
18           shoppingCart="{cart}"/>
19        <CartView id="cartView" cartData="{cart}"
20           checkOut="changeView('checkout')"/>
21     </mx:VBox>
22   </mx:HBox>
23 </mx:Application>

When you create classes in MXML or Action Script, you can use these classes as tags in your main application file (or in any other component). There is no additional step required to create tags.

For example, to hold the items purchased by the user, you declaratively set up a ShoppingCart in flexstore.mxml (line 3). An instance of the ShoppingCart class (described in the Model Classes section above) is created behind the scenes.

Similarly, the CartView class described in the “View Classes” section above is used as a tag (line 19) to display the contents of the shopping cart.

Loose Coupling of Application Components

Loose coupling of components is another proven best practice in object-oriented development. Loose coupling is a programming technique that consists in avoiding interdependencies between classes as much as possible. Loose coupling increases the reusability of your components throughout and across your applications.

The basic idea is that the more a component knows about other components, the less reusable that component is. In other words, if component A has a strong reference (a typed variable) to component B, you can only reuse component A along with component B. This kind of dependency is generally undesirable.

You can often avoid direct references to other components by using event notifications between components. For example, the CartView class has a Checkout button that allows the user to initiate the checkout process. However, the CartView class has no knowledge of the Checkout class. When the user clicks the Checkout button, the CartView object dispatches a "checkout" event (line 25 in the CartView.mxml example above). The Flex Store application is registered as a listener for that event and displays CheckoutView (line 21 in the flexstore.mxml example above).

Similarly, when you click an item in the product catalog, details for the selected product display in the Product Details View. However, the ThumbnailView class (ThumbnailView.mxml) has no reference to the ProductDetail class (ProductDetail.mxml). When you click a product, the ThumbnailView object dispatches an item Selected event. The Flex Store application is registered as a listener for that event and makes its selectedItem instance variable point to the clicked product (line 14 in Flex Store.mxml above). Because the productData attribute of the ProductDetail object is bound to selectedItem, the details for the clicked product automatically appear in the ProductDetail component.

Summary

Flex provides developers with a familiar and popular programming model: The combination of a tag-based language, MXML, to create the user interface and a traditional OOP language, Action Script, to create faceless classes for the application. Using this powerful programming model, Flex developers can build applications using proven software engineering methodologies, design patterns, and best practices. This article highlighted some of the basic concepts behind the MVC architecture and loose coupling of application components. Flex developers can take these concepts as far as their application requires.

About the author

Christophe Coenraets is a Technical Evangelist for Adobe where he focuses on rich Internet applications and enterprise integration. He has been working on Flex since the early days of the product in 2003. In his previous role at Macromedia, Christophe worked on JRun, the company's J2EE application server. Before joining Macromedia, Christophe was managing Java and Internet applications evangelism at Sybase. Christophe has been a regular speaker at conferences worldwide for the last 15 years. He blogs at http://coenraets.org.