Accessibility
Peter Ent

Peter Ent

Adobe

Created:
6 February 2006
User Level:
Beginner
Products:
Flex

Loose coupling in Flex applications

Loose coupling is a technique you can use to write better Flex code. When using loose coupling, you write components for your applications in a reusable way that reduces interdependencies between the components. You pass information between the components using events. Since this is the structure of the Flex framework, this technique provides an excellent model for your own code.

By using this technique, you can create applications that are easier to maintain, you can develop applications more quickly, and you can build them with less overall cost. This article shows a short example of the loose coupling technique and some of the pitfalls when the technique is not used, which lead to higher development costs.

The Scenario without Loose Coupling

Let's suppose that you have a Flex application structured as follows:

Application
   var orderArray; // via a data service

   HBox
      Panel (OrderPanel.mxml, figure 1)
         DataGrid id="orders"
         ... item1
         ... item 2
         .. etc.
   ViewStack
      HBox
         ... some components
      VBox id="orderDetail" (OrderDetail.mxml, figure 2)
         Label id="orderID"
         ... other components

This pseudo code creates the order panel and the order detail (Figures 1 and 2).

Order Panel

Figure 1. Order Panel

OrderDetail component

Figure 2. OrderDetail component

On the main application level, you have some components, some of which are named OrderPanel and OrderDetail, and which may be in custom component files. The main application also has the data service connection (perhaps a RemoteObject) and holds the orderArray.

Let's say that you want to display the contents of the orderArray in the DataGrid child of OrderPanel and, when a user clicks on a row of that DataGrid, have the details of the order display in the OrderDetail component, such as the orderID Label child. Notice that OrderPanel and OrderDetail are not siblings. They are also in separate files—they are custom components.

One way to link orderData to the DataGrid is to use something similar to the following code:

<mx:DataGrid id="orders" dataProvider="{mx.core.Application.application.orderArray}" change="showDetails()" />

And then write the showDetails function as follows:

function showDetails() {
   mx.core.Application.application.orderDetail.showDetails( orders.selectedItem );
}

This solution assumes that the OrderDetail component has a public function named showDetails. While this solution works, there are several problems with it.

With Tight Coupling, Applications Don't Scale Well

What if you need to rename the orderDetail component to something else? You would have to search throughout your application to find all instances of it and change it.

What if you or someone else decides to remove the ViewStack from the main application, putting it into its own component or nesting it in another component? Again, you would have to find all the places being referenced and change the code.

What if you want to have another component such as a chart that also displays order information when user selects the DataGrid row? The way you have written the application, the OrderPanel code only directly accesses the OrderDetail component. You could add another statement to the change handler, but what if there were more and more parts of your application that need the information?

As you can see, the strategy you used to structure your application can quickly spiral out of control. As other developers and designers work on the project, the links between various parts of the application become harder to find and update. Code maintenance becomes a nightmare and bottleneck. Adding more people to the project doesn't help because each new member has to find his or her way through the mess and really understand how each part relates to make any changes.

This is where loose coupling becomes essential in your application. What that means is that most components do not depend on each other, but are linked together through events and properties. In general, the rule of thumb is that parents can access their immediate children's functions and properties, but children may not reach up the tree or to siblings (and cousins).

The Benefits of Loose Coupling

In the following example, the DataGrid in OrderPanel has an array of information:

<mx:Script>
    public var dataProvider:Array;
    private function showDetails(event) {
       // see below
    }
</mx:Script>

<mx:DataGrid dataProvider="{dataProvider}" change="showDetails(event)" />

Notice that the DataGrid's dataProvider property is bound to a local, public variable. In this example, I named the property dataProvider to be consistent with the Flex framework; when you use OrderPanel anytime, it should refer to a dataProvider property.

At the application level, the orderArray can be passed to the OrderPanel through dynamic data binding:

<local:OrderPanel dataProvider="{orderArray}" />

Now you can rename orderArray and you will not have to search for and update references to it anywhere but in this one file.

Next, modify the OrderPanel component to handle selecting an item from the DataGrid; change the OrderPanel component so that it throws its own event (the event is called orderSelect for this example) and provide a public accessor (a variable in this case) to get to the selected order.

<mx:Metadata>
   [Event("orderSelect")]
</mx:Metadata>

<mx:Script>
    public var dataProvider:Array;
    public var selectedOrder:Object;

    private function showDetails(event) {
        selectedOrder = event.target.selectedItem;
        dispatchEvent({type:"orderSelect"});
   }
</mx:Script>

Now when the user clicks the mouse in a row of the DataGrid in the OrderPanel component, the Flex application dispatches an orderSelect event. Any components that want to use this event can find out which order was selected by using the selectedOrder property.

This is a cornerstone of loose coupling. If you have an event on a child within a component and you want code outside of the component to use it, create an event on the component and dispatch that event. In Flex 2 you will be able to make these internal events accessible to outer components, but for now, consider creating your own events with meaningful data accessors, such as selectedOrder.

Now that the OrderPanel component does not rely on any other part of the application. But what about the OrderDetails component? The OrderDetails component already has a function that can take a record of the data and display it. All the OrderDetails component needs to be complete is to call this function when the application dispatches the orderSelect event.

In the main application, change the OrderPanel tag as follows:

<local:OrderPanel dataProvider="{orderArray}" orderSelect="orderDetail.showDetails(event.target.selectedOrder)" />

Now, the OrderPanel and OrderDetail components are loosely coupled, where before they were tightly coupled. Components always know something about each other; that's why the term is loosely coupled and not uncoupled.

By using the Flex framework as a guide and following its conventions, however, you can integrate your own components seamlessly and make them much more reusable. If you need to move the OrderPanel component around, for example, or change the layout of the OrderDetails component, you can do so without worrying about the rest of the application.

As you develop your applications, an event-driven framework, like Flex, provides an opportunity to improve code efficiency, speed development, and make maintenance a breeze.

About the author

Peter Ent is a Computer Scientist at Adobe, working on the Genesis project. Prior to this, Peter worked for Adobe Customer Care as a Flex Support Engineer and then as a Technical Account Manager. Before joining Adobe, Peter worked in the financial services industry at State Street and Fidelity Investments. He also has experience at two start-ups building software applications doing imaging and molecular modeling. Peter holds a bachelor of science in Computer Science from Syracuse University. Visit Peter's blog.