Flex Best practices. Sketch 1: An application with a single Event class

This is the first of the series of articles that Flex architects from Farata Systems will be posting over the next several months. We “ll introduce you to our own class library that goes by a working name theriabook. Over the last couple of years we “ve been successfully using various coding techniques and custom components that turned the application development in Flex into a RAD project.

I “ll start with some history and definitions. While working on the book “RIA with Flex and Java rdquo;, we “ve been building a library of reusable components for the book samples. Since the book writing was our moonlight activity, we “ve had a chance to try all these components at the battlefield ndash; during our consulting gigs with various clients. Unfortunately, last week we “ve had to politely reject the offer of our publisher, Sys-Con Media for writing the second edition of that book. We just do not have time. So if you are thinking of purchasing a copy, do it sooner than later – it “ll be gone soon.

There are three ways of writing software:

1. Just write the code from scratch

2. Pick a framework and write the code by the rules dictated by this framework

3. Use selected components from one or more class libraries

To see the difference between a framework and a class library, visualize a construction site of new housing development. In one home site, you see a frame of the future house, rooms are laid out, and electrical wire are hanging everywhere . The site next to it just has a pile of construction materials ndash; Anderson windows, 2X4th, et al. Of course, the latter gives you a lot more freedom as to how your future house will look like hellip;as long as you know how to construct it.

We like freedom, and will be presenting not only our “Anderson windows rdquo;, but also instructions for using them during construction of your application. Best practices, as we currently see them. Your input is greatly appreciated and if you have your own construction materials or tricks of the trade, please add them to our pile.

All objects from our theriabook library will be available for free as an open source software governed by the MIT license ndash; the same as Flex framework.

Without further ado, let “s go to our first best-practice.

An Application With a Single Event Class

Flex is all about event-driven development. Create loosely coupled objects and let them send events to each other. You can read about this in the following blog

In a nutshell, you can create new events for every occasion you need. If an event does not need to carry any additional data, just extend flash.events.Event, and define the meta-tag to help Flex Builder listing this event in its type-ahead prompts and dispatch it when appropriate. If your new event needs to carry some data, create an ActionScript class, define a variable in your subclass to store your data, and override the method clone();

If we take a mid-size Web site with 10 views, where each view has two components that can send/receive two events, you can quickly rich forty or more custom Event-based classes that look pretty much the same. To ensure that the situation does not go out of control, some of the Flex frameworks force you to register upfront each event in a central location.

We say, “No need to do it. You can get away with one event rdquo;. So a sample application below has only one defined event class that can fit multiple purposes without the need to introduce tight coupling between your application components.

To illustrate the concept, I “ve created a simple application that looks as follows:

This application consists of two modules (GreenModule and RedModule) that are loaded in the same area of the main application on the click of the appropriate Load button. It also has one universal event class called ExEvent. If you click on the Send buttons, an instance of this event is created and you can put there an instance of Object, a DTO, a couple of string variables, nothing, or anything else you like. In this example I “m using a DTO class called GirlfriedDTO.as. There is no mapping between the event you send and the modules. For example, if you send a Green event to the Red module, nothing happens since the Red module is not listening to the Green event.

I “ve been using modules in this application not because I endorse them, but rather because they give me a chance to quickly illustrate a concept of run-time loading and lose coupling between the objects and events. Victor Rasputnis, my colleague at Farata Systems has been experimenting with modules and next month will publish an article describing his findings.

A completed application and its source code is deployed at this URL. Its Flex Builder “s project has a folder modules that contains two modules ndash; red and green. The red one is listening for the arrival of the girlfriend “s first and last name packaged in our single event class as two separate strings:

lt;?xml version= “1.0 ” encoding= “utf-8 “? gt;

lt;mx:Module xmlns:mx= “http://www.adobe.com/2006/mxml ” layout= “absolute ”

width= “100% ” height= “100% ” creationComplete= “onCreationComplete(event) ” gt;

lt;mx:TextArea id= “display ” backgroundColor= “#FF4949 ” width= “100% ” height= “100% ” fontSize= “28 “/ gt;

lt;mx:Script gt;

lt;![CDATA[

private function onCreationComplete(evt:Event):void{

this.addEventListener( “RedGirlfriend “, onRedGirlfriend);

}

private function onRedGirlfriend(evt:ExEvent):void{

display.text= “My girlfriend is “+ evt.fName+ ” ” + evt.lName ;

}

]] gt;

lt;/mx:Script gt;

lt;/mx:Module gt;

The green module expects girlfriend “s name in a form of GirlfriendDTO:

lt;?xml version= “1.0 ” encoding= “utf-8 “? gt;

lt;mx:Module xmlns:mx= “http://www.adobe.com/2006/mxml ” layout= “absolute ” width= “100% ” height= “100% ”

creationComplete= “onCreationComplete(event) ” gt;

lt;mx:TextArea id= “display ” backgroundColor= “#9CE29C ” width= “100% ” height= “100% ” color= “#070707 ” fontSize= “28 “/ gt;

lt;mx:Script gt;

lt;![CDATA[

import dto.GirlfriendDTO;

private function onCreationComplete(evt:Event):void{

this.addEventListener( “GreenGirlfriend “, onGreenGirlfriend);

}

private function onGreenGirlfriend(evt:ExEvent):void{

var myGirlfriend:GirlfriendDTO=evt[ “girlfriend “];

display.text= “My girlfriend is “+ myGirlfriend.fName+ ” ” +

myGirlfriend.lName ;

}

]] gt;

lt;/mx:Script gt;

lt;/mx:Module gt;

The GirlfriendDTO is located in the folder dto and is pretty straightforward too:

package dto

/**

* This is a sample data transfer object (a.k.a. value object)

*/

{

public class GirlfriendDTO

{

public var fName:String; // First name

public var lName:String; // Last name

}

}

Now let “s talk about our single but universal event class. It “s based on the DynamicEvent class, which allows you to add any properties to the event object on the fly. Surprisingly, Flex documentation discourages you from using this class. Here “s what it reads:

This subclass of Event is dynamic, meaning that you can set arbitrary event properties on its instances at runtime. By contrast, Event and its other subclasses are non-dynamic, meaning that you can only set properties that are declared in those classes. When prototyping an application, using a DynamicEvent can be easier because you don ‘t have to write an Event subclass to declare the properties in advance. However, you should eventually eliminate your DynamicEvents and write Event subclasses because these are faster and safer. A DynamicEvent is so flexible that the compiler can ‘t help you catch your error when you set the wrong property or assign it a value of an incorrect type.

Let me respectfully disagree with this recommendation and suggest you to use the dynamic nature of this event not only for prototyping, but also for development and deployment of your applications. When GUI components send event to each other, the difference in the processing of your dynamic vs. static event instance is negligible. It “s not clear how safer the static event are. I do not think so.

When you design an event-based interaction between components of your applications, both the sending and receiving parties must know in which format the data are being delivered by an event. And we utilize this knowledge even in case of the dynamic events. We can use either a well defined GirlfriendDTO:

var myDTO:GirlfriendDTO=new GirlfriendDTO();

myDTO.fName= “Mary “;

myDTO.lName= “Poppins “;

var greenEvent:ExEvent=new ExEvent( “GreenGirlfriend “);

greenEvent.girlfriend=myDTO;

someObject.dispatchEvent(greenEvent);

or just add two string variables:

var redEvent:ExEvent=new ExEvent( “RedGirlfriend “);

redEvent.fName= “Mary “;

redEvent.lName= “Poppins “;

someObject.dispatchEvent(redEvent);

In this sample I use an ExEvent, which is a subclass of the DynamicEvent ndash; it just has a little enhancement that eliminates manual programming of the property Event.preventDefault:

package

{

import mx.events.DynamicEvent;

public dynamic class ExEvent extends DynamicEvent

{

private var m_preventDefault:Boolean;

public function ExEvent(type:String, bubbles:Boolean = false,

cancelable:Boolean = false) {

super(type, bubbles, cancelable);

m_preventDefault = false;

}

// It ‘s an enhancement: DynamicEvent class does not

// automatically process preventDefault in cloned events

public override function preventDefault():void {

super.preventDefault();

m_preventDefault = true;

}

public override function isDefaultPrevented():Boolean {

return m_preventDefault;

}

}

}

Now the code of the test application loads modules, and then the user can send any event to whatever module is loaded at the moment. Of course, if the currently loaded module does not have a listener for the event you “re sending, tough luck. Do not expect miracles ndash; nothing will happen. But the good news is that it won “t break the application either:

lt;?xml version= “1.0 ” encoding= “utf-8 “? gt;

lt;mx:Application xmlns:mx= “http://www.adobe.com/2006/mxml ” layout= “vertical ” viewSourceURL= “srcview/index.html ” gt;

lt;mx:HBox gt;

lt;mx:Button label= “Load the Green Module ” click= “loadMyModule( ‘modules/GreenModule.swf ‘) “/ gt;

lt;mx:Button label= “Load the Red module ” click= “loadMyModule( ‘modules/RedModule.swf ‘) “/ gt;

lt;mx:Button label= “Send Green Event with Object ” click= “sendGreen() “/ gt;

lt;mx:Button label= “Send Red Event Event with two strings ” click= “sendRed() “/ gt;

lt;/mx:HBox gt;

lt;mx:Panel width= “100% ” height= “100% ” title= “A module placeholder ” layout= “absolute ” gt;

lt;mx:ModuleLoader id= “theModulePlaceholder ” width= “100% ” height= “100% “/ gt;

lt;/mx:Panel gt;

lt;mx:Script gt;

lt;![CDATA[

import dto.GirlfriendDTO;

//Load the module specified in the moduleURL

private function loadMyModule(moduleURL:String):void{

theModulePlaceholder.url=moduleURL;

theModulePlaceholder.loadModule();

}

// Sending generic ExEvent adding an object that contains

// the name of the girlfriend

private function sendGreen():void{

// Strongly typed DTO – better performance and readability,

// but its structure has to be known for both parties –

// the main application and the module

var myDTO:GirlfriendDTO=new GirlfriendDTO();

myDTO.fName= “Mary “;

myDTO.lName= “Poppins “;

if (theModulePlaceholder.child !=null){

var greenEvent:ExEvent=new

ExEvent( “GreenGirlfriend “);

greenEvent.girlfriend=myDTO;

theModulePlaceholder.child.dispatchEvent(greenEvent);

}

}

// Sending a generic ExEvent that holds the name of the girlfriend

// as two separate variables

private function sendRed():void{

var redEvent:ExEvent=new ExEvent( “RedGirlfriend “);

redEvent.fName= “Angelina “;

redEvent.lName= “YouKnowWho “;

if (theModulePlaceholder.child !=null){

theModulePlaceholder.child.dispatchEvent(redEvent);

}

}

]] gt;

lt;/mx:Script gt;

lt;/mx:Application gt;

The function sendGreen() sends an instance of our ExEvent event with DTO, while the sendRed() just adds two properties fName and lName to the instance of the ExEvent.

Instead of using a well defined DTO, I could “ve used a weakly typed data transfer object:

var myDTO:Object={fname: “Mary “,lname: “Poppins “};

But this would result in poor readability of the code and a bit slower performance. On the positive side, there would be no need to explicitly define and share the class structure of the dto between the app and the module. I “d do something like this during the prototyping stage, but not in a real code.

Let “s recap. What did we gain? No need to create lots of tedious coding defining dozens of similar event classes. What did we lose? Since we did not use the metatag Event declaring the names of the events those never declared event classes, Flex Builder won “t be able to help us with the name of the event in its type-ahead help. No biggie.

In the unlikely case if there is a view in your application that can “t afford to lose a couple of milliseconds caused by using dynamic event, use static but in that view only. But with a single dynamic event the code base of your project will become smaller, and more readable.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s