Accessibility
 
Home / Developer Center / Flash Remoting Developer Center /

Flash Remoting Article

Icon or Spacer Icon or Spacer Icon or Spacer
 
Sean Corfield
www.corfield.org
 
Software design patterns for Macromedia Flash Remoting

In a Rich Internet Application, a Macromedia Flash MX client provides the rich user experience, while server-side programming (based on Macromedia ColdFusion MX in this article) provides the business logic and manipulates the data model. Macromedia Flash Remoting enables communication between the two.

Consider the performance of such an application. Several key factors impact performance, such as the size and complexity of the Macromedia Flash MX client and the number of connections and calls made from the client to the server.

 

By definition, a Macromedia Flash MX movie with a lot of complex ActionScript is larger than a movie containing simpler logic. It takes longer to download. A complex client also requires more client-side CPU power.

It's a common challenge: You want to produce a rich user experience but you don't want to burden the client movie with a lot of complex logic. On the other hand, if you move all your logic to the server side, the client will have to make a lot of network calls to invoke methods and retrieve data piece-by-piece. This reduces performance because your application continually waits for network responses.

This article examines how you can manage this trade-off by applying well-known software design patterns, such as façade and value-object patterns, and illustrates it by means of simple fictional e-commerce website application.

Description of fictional e-commerce site "buying.com"
This fictional website's Macromedia Flash MX user interface lets shoppers browse a product catalog, look at the details for a product, put products in a shopping cart, and go through a checkout process with credit card authorization.

The back end of buying.com runs on ColdFusion MX and consists mainly of ColdFusion Components (CFCs) that handle each of the main activities:

catalog.cfc
product.cfc
cart.cfc
checkout.cfc

Each component contains methods that support the possible user interactions on the website. For example, the methods in product.cfc return different attributes of the product. The methods for cart.cfc allow a customer to put an item into the cart, update its quantity, and retrieve the details of an item in the cart. For checkout.cfc, there are multiple methods: four separate methods gather the user's name, billing address, shipping address and credit card respectively, a method that authorizes payment, and another method that completes the checkout.

In a naïve implementation (an unsophisticated implementation, one that doesn't take into account best architecture practices), the Macromedia Flash movie would probably make a NetService connection to the gateway for each of these services, make several remote calls to each service, and manipulate the data returned by each call. The naïve implementation ends up with a large, complex client that makes several connections and many calls (see Figure 1).

 

Figure 1. A naïve implementation of the e-commerce site

 

Figure 1. A naïve implementation of the e-commerce site

Reducing the number of calls
Several of the back-end CFCs offer set/get methods to provide access to data. Generally, this is proper coding practice because it avoids exposing the underlying data members of the components. For example, product.cfc has methods to get the product name, get the description, get the price, get the icon, and so on. When you use this component locally—for instance, from other components or CFML pages—the number of calls it must make may not impact performance significantly. When this component is used remotely through Macromedia Flash Remoting, however, each call creates network traffic and requires both a result callback (for a successful call) and a status callback (for an unsuccessful call) in ActionScript.

This situation is similar to J2EE development when the client layer makes calls to remote EJB instances. To solve this problem, you pass back a single object containing all of the data the client needs, instead of making multiple calls to retrieve each piece of data. This is known as the Value Object pattern. On the Sun Microsystems website, Sun describes the Value Object pattern in the J2EE pattern catalog as follows:

Use a Value Object to encapsulate the business data. A single method call is used to send and retrieve the Value Object. When the client requests the enterprise bean for the business data, the enterprise bean can construct the Value Object, populate it with its attribute values, and pass it by value to the client.

Because Macromedia Flash Remoting can handle complex and simple object types, you can "borrow" this pattern for your Rich Internet Application. In this case, the Value Object will most likely be a native ColdFusion type—such as an array, struct, or query—that can be passed through Macromedia Flash Remoting and be manipulated as a native ActionScript type in the client.

Many components, such as product.cfc in the example below, perform a database query to retrieve underlying data and expose that data through several get methods.

 
<!--- product.cfc --->
<!--- without Value Object pattern - lots of 'get' methods --->
<cfcomponent>
<cffunction name="getName" returntype="string">
<cfargument name="id" type="string">
...
</cffunction>
<cffunction name="getPrice" returntype="numeric">
<cfargument name="id" type="string">
...
</cffunction>
...
</cfcomponent>

These components can just as well return the entire query result, which becomes a recordset in ActionScript. The client can easily extract the data from the recordset instead of making multiple calls.

<!--- product.cfc --->
<!--- with Value Object pattern - single 'get' method --->
<cfcomponent>
<cffunction name="getProductInfo" returntype="query">
<cfargument name="id" type="string">
...
</cffunction>
...
</cfcomponent>

The ActionScript changes from making calls, in the first example, to getName(), getPrice(), and so forth to making a single call, in the second example, to the getProductInfo() method and then extracting the name, price, and so forth from the recordset returned.

For the checkout.cfc component described above, clients would have to make separate calls to set each of the billing address, shipping address and credit card information.

<!--- checkout.cfc --->
<!--- without Value Object pattern - several 'set' methods --->
<cfcomponent>
<cffunction name="setBillingAddress">
<cfargument name="address" type="struct">
...
</cffunction>
<cffunction name="setShippingAddress">
<cfargument name="address" type="struct">
...
</cffunction>
<cffunction name="setCreditCard">
<cfargument name="card" type="struct">
...
</cffunction>
...
</cfcomponent>

Instead of passing a struct that contains an address to each of the setXxxAddress methods and a struct containing the credit card details, you would build a single struct in ActionScript (with an entry for each billing address, shipping address and credit card), and then pass that aggregate struct to setCustomerDetails. In this way, you are making one call instead of three, or one serialize/deserialize operation instead of three, which means less traffic through the Macromedia Flash Remoting gateway.

<!--- checkout.cfc --->
<!--- with Value Object pattern - single 'set' method --->
<cfcomponent>
<cffunction name="setCustomerDetails">
<cfargument name="customer" type="struct">
...
</cffunction>
...
</cfcomponent>

You might be concerned that this increases the complexity of the client. In reality, it's just a trade-off between two different types of complexity:

In the naïve implementation, the client makes multiple calls and must coordinate all of the result/status callbacks.
In the Value Object implementation, the client makes a single call, stores the result locally, and then accesses the data from that local object (or constructs a single local object with all of the client data, and makes a single call to pass it to the server).
 

Reducing the client's dependencies
Buying.com's back end contains only four components. The client movie interface does not have to manage too many service connections. As you enhance this website, however, the number of components that the client would need to interact with increases. Consider if you were to add the following functionality to your application: a membership function so users could return and view their order history, an address book for users to save multiple billing or shipping addresses, a promotions system to reward loyal customers and tempt new ones, and cross-selling and bundling for products. Each of these enhancements is likely to add at least one ColdFusion component to the system and, therefore, increase the number of service handles obtained from the gateway.

Furthermore, the client movie ends up with a lot of code that is specific to the individual components and the client code becomes harder to maintain because changes to the back-end components often require changes to the client layer. Also consider that services exposed to Macromedia Flash Remoting are also necessarily exposed as general web services, providing you the opportunity to offer your online store as a service to a large number of users with a variety of different interfaces. The four components discussed so far would not make an ideal interface for a general web service!

Note that a very simplistic naïve implementation would probably create a NetService connection object for each component, possibly for each group of related method calls. This can be mitigated purely within the Macromedia Flash movie by using a single NetService connection object passed around in global scope and, if necessary, saving each of the service handles to the global scope as well. It should be evident that the real challenge here, in terms of complexity, is having to manage multiple services in the first place.

Creating a solution in a façade design pattern
Enter a software design pattern called a façade. From the "Gang of Four" book, Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley, 1995), façade is defined as follows:

Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.

The façade that you create is a single ColdFusion component that only exposes whatever functionality is necessary to implement your online store. You will choose methods in the façade that make sense to the client. (Note that the four existing components most likely have methods that make sense to the component in which they are defined.)

Some of these façade methods will aggregate the functionality of several back-end methods and manage their interactions. For example, whereas cart.cfc has a method called updateQuantity that updates the quantity of a specific item, the client would typically update all of the quantities at once, so the façade would have a method called updateCartQuantities that takes an array of quantities and iterates over the array, calling cart.updateQuantity to update the quantity for each item. Common patterns for user interaction such as this can be moved from the client movie to the façade, which simplifies the client and reduces the coupling between the client and the specific back-end components. Figure 2 shows a façade implementation for an example e-commerce site.

 

 

Figure 2. A facade implementation of the e-commerce site

 

Figure 2. A façade implementation of the e-commerce site

Unlike the naïve implementation shown in Figure 1, now there is only one NetService connection object needed. The storefaçade.cfc component has absorbed some of the remaining complexity of the client:

<!--- storefaçade.cfc --->
<cfcomponent>
<!--- product services --->
<cffunction name="getProductByID" returntype="query">
<cfargument name="id" type="string">
<cfinvoke component="product" method="getProductInfo"
id="#arguments.id#" returnvariable="result">
<cfreturn result>
</cffunction>
...
<!--- checkout services --->
<cffunction name="customerCheckout">
<cfargument name="customerDetails" type="struct">
<cfinvoke component="checkout" method="setCustomerDetails"
customer="#arguments.customerDetails#">
<cfinvoke component="checkout" method="doCheckout"
returnvariable="result">
<cfreturn result>
</cffunction>
...
</cfcomponent>

Notice how the façade allows you to provide better names for the services and to combine actions, such as setting the customer details and performing the checkout all in one call.

Extending the e-commerce web application
One possible future enhancement for your e-commerce application is to add membership functionality so that users can create accounts, log in, store their billing and shipping addresses, and review their order history. Membership may be provided by components such as authenticate.cfc and userprofile.cfc, but because this is something you'd want to use in several of your websites, you should consider how to add this in the most reusable manner. Instead of modifying the storefaçade.cfc component to invoke these two new components, consider creating a more generic membershipfaçade.cfc that provides the necessary services using these two new components (log in, log out, create account, update profile and so forth).

Changing storefaçade.cfc to extend membershipfaçade.cfc adds in all the new membership functionality, so that the Macromedia Flash MX client can access it in the online store. The store façade provides an account history method that combines the functionality from the membership façade (user profile) with that of the checkout process, and records each user's orders in his or her profile.

Alternatively, you might create a Macromedia Flash MX client for the membership façade to provide a "membership hub" where users can manage all generic aspects of their accounts. The online store's Macromedia Flash movie can then load the membership movie and tell it to connect to the single storefaçade.cfc service that the online store already manages. Figure 3 shows a membership/store façade implementation.

 

Figure 3. Membership/Store facade implementation

Figure 3. Membership/Store façade implementation

By applying two fairly straightforward design patterns, Façade and Value Object, that are typically used in the C++ and Java worlds to your Macromedia Flash MX and ColdFusion MX application, you have simplified your Macromedia Flash MX client and reduced the amount of network traffic the application generates. Both of these factors improve the performance of the application.

Selecting suitable high-level façades for segments of your application makes it easier for you to extend and enhance your application, while retaining the performance benefits of these patterns.

 


About the author
Sean Corfield, Macromedia's director of architecture, brings 20 years of technical and managerial experience in architecture, web technologies, and programming languages. He has expert knowledge in UML, OOA/D, CASE, C, C++, Java, SQL, Broadvision, ColdFusion, and HTML. He relishes a technical challenge both inside and outside of work and healthy technical debates. You can contact him at scorfield@macromedia.com.