Loose v. strong-typing in Actionscript

One of my pet peeves about Flash development is the very loose nature in which most of us code Actionscript. Loosely typing/handling things is nice at first, but has a way of eventually coming back to bite you. One of the most common cases this happens is dispatching events.

Generally, one creates an instance of the generic Object class, stuffs it with whatever pieces of data are necessary for any and all listeners of that event, and off they go, dispatching free pieces of information to any object subscribed to listen. And, often is the case where, later on, we figure out that this event needs to pass along additional pieces of information. So, because of the nice nature of loose typing, we just append more properties onto the Object instance, naming it however we want, and then pull it down from a particular class’s listener method.

That’s fine and dandy. We do this same loose typing with arrays… stuffing whatever kinds of custom object instances into them and then pull them out freely, whether myArray[i] happens to be a String or an instance of myFavoriteCheeseIconsButtonUIClips.

But, loose typing has its costs. Months later, I go back to a class file, and find a listener method. I can see it accepts a generic object as a parameter, and in the code itself is a myriad of random attributes off that object. To modify that piece of code, I have to go back to the class that dispatched the event and find out what that generic object is made out of. And, if I needed to pass along more information, I need to trickle back and see how the current pieces of information were constructed and go headhunting for that other bit of info that I need in the dispatching class. A royal pain in the arse.

The end result is that, when I go back after I’ve forgotten about the code for awhile, loose typing gives me no time gain (in fact, time loss). And, there’s absolutely no way that I can predict or deduce any other information from all that loose passing of random data across the event.

At XO, we stress passing strongly typed objects when dispatching events. An event, like, “ProductConfigurationUpdated” shouldn’t just pass a messy object like {id:339, part:Axel, color:Silver, userAcct: 22}. Instead, we should create some value objects… perhaps, a ProductItem and UserItem object. Then, we could modify the code to pass something like {productItem:myProductItem, userItem:currentUser}. Event listeners now have access to strongly-typed objects, the definitions of which would be found in the custom classes we created for them.

When it inevitably becomes time to modify the event listeners for ProductConfigurationUpdated, or the method that dispatches ProductConfigurationUpdated, we can much more easily see whether modifications are needed. Suppose an event listener method needs to display the product’s general size. Without even going into the event dispatcher code, we can easily guess that myProductItem (the ProductItem instance passed through the event) will contain that info (and, if I wanted to know exactly what ProductItem should contain, just go hunt down the ProductItem class and look at its publicly available properties and methods). Now, suppose another event listener method needs to know about the state of the current product configuration, by the value objects passed, it’s safe to assume that information isn’t there. Instead, we’ll probably need to pass an array of these ProductItems through the event…

Which brings up another loose/strong typing situation. Instead of passing a generic array, we might consider building a ProductCollection class – essentially a wrapper class for an array that will cast back each item as a ProductItem. This is another practice we maintain at XO – replacing arrays with strongly typed custom collections. We use a custom collection class that provides us with nice features like Get(_index:Number)to retrieve any item in the collection by an index, but have it handed back to us casted as the item. So, a ProductCollection instance can only store ProductItem instances, and automatically give you back ProductItem instances (not generic objects).

At first, you may find this limiting… why use a typed collection when an array can hold any number of different kinds of objects? It all comes down to practical use. When you code, you start finding out you’d rarely throw together items that are of all different types into an array. And, think of the opposite scenario. If you do want an array to store a million different types of things in there, the code necessary to figure out what those generic objects really are when you try to access them will become a nightmare.

The more common scenario is that you might have a collection of items grouped together that are somewhat (but not altogether) different. For instance, if you’re building a shopping cart in Flash, you might consider an ItemsCollection which will be a wrapper class for an array that stores all the items you can buy at a grocery store. This might contain things like fruits, vegetables, dairy, and meats. But, rather than actually creating a Fruit, Vegetable, Dairy, and Meat class, you might create a general FoodItem class with an internal type value. Or, you might find there’s enough unique functionality for each of these kinds of foods that separate classes are important…but they can all inherit from a FoodItem base class or a FoodItem interface. The ItemsCollection class can then be created to accept only FoodItems (as a base class) or iFoodItems (as an interface). The lesson is, you find the common traits among things you store together, and that becomes a good basis for creating a new model.

None of what I mentioned above is really anything new, especially if you’ve been doing OOP for a while. However, I find that strong-typing is even more critical in ActionScript – given that coding a stateful application requires lots of loose coupling (i.e. having an event driven model), it is strongly-typed value objects that provide the good glue to bind loosely coupled event dispatchers and listeners together.

When you start getting into the habit of adhering to sensible value objects and using them as parameters for methods or as passed objects through events, you’ll start to reap the benefits of maintainability. You’ll also start seeing your Flash applications as, not a beautiful UI sitting in front of a complex mess of dispatched generic data. Rather, it becomes a beautiful UI sitting on top of a very predictable, readable bed of data.