Category Archives: Uncategorized

Book review: ActionScript Graphic Cookbook by Peter Backx and Dominic Gélineau

book cover
ActionScript Graphic Cookbook
Backx, Peter and Gélineau, Dominic
2012, Packt Publishing
978-1-84969-320-2

This is a cookbook, a book of recipes; it is not a reference or teaching book; you will not have a comprehensive library at the end. This book give specific solutions to specific needs. A teaching book might show a finished chart with call-outs explaining how to create or configure the pieces, but a recipe is not an analysis: it starts with the least foundation it can and works towards a finished graphic. This book will show you how to create graphic representations of data; it will not tell you when to use a particular technique.

It is also not a users’ manual for the Data Visualization chart library from Adobe, although the recipes in the middle of the book use that library. For simple line charts (e.g. sparklines), the recipe describes how to draw the lines oneself using the ActionScript graphic primitives. For advanced rotatable 3-D charts (which Data Visualization does not support) and 3-D landscapes, it uses advanced geometry and low-level polygon fills. While these are not Flex components (the code is pure ActionScript with mostly Sprite-based classes, many recipes are connected to data, sometimes dynamically.

Each recipe presents as a set of sections: the title, Getting ready, How to do it…, How it works…, There’s more…, and See also. Besides the inconsistent use of ellipsis, the title section (which describes the need) is often perfunctory and sometimes omits a picture of the finished graph or chart (i.e. the tempting photo of the finished dish). While some How it works… sections show additional (but too few) images, a graphics book should err on their side of too many images, and certainly should always have one as part of the recipe’s description.

Within sections, some of the recipes do built on the previous one a bit: graphic enhancements, adding different data sources, or using a more complex representations. The sections cover

  • Drawing with the core ActionScript objects
  • Representing sets of data in graphs
  • Bar charts (using Adobe’s Data Visualization library)
  • Advanced charts without the Data Visualization library
  • Charting Data on Maps
  • Animation and Zooming in on Data
  • Showing Network Data Relationships Graphically
  • Rotatable 3-D Charts and Data Landscapes

The book is available in Kindle and paperback editions as well as PDF, mobi, and epub direct from the publisher. The PDF seems to be images of the pages, not text (no copy-and-paste, no external links, and no links from the table of contents). It is also available on-line from the publisher’s site once purchased. The HTML presentation, often being very wide, actually makes the chapters easier to read than the book format: the code does not need to wrap; the images are visible on the same “page” as the rest of the recipe, and the links work.

Some recipes need to import data from files or web services and include code and discussion to do so; these pedestrian routines (and some entire recipes!) distract from the topic of graphic functionality; perhaps they could have been relegated to an appendix. Some recipes, perhaps acknowledging that supporting code is large and tedious, direct the user to download files from the Packt Publishing website and “… follow along”.  The index is 12 pages long; very respectable for a 280 page book.

For its niche, it is likely the definitive reference. It does not address the relative merits of using a well-known charting library vs. using trigonometric functions and low-level drawing functions; clearly these include abstraction and performance. Cookbooks don’t offer a questionnaire; they just tell you how to make a great souffle  Joe Bob says: check it out.

The Only Good Comment Is a Useful Comment

I’ve talked about comments in The Zen of Comments, but the rising tide of ASDocs (and JDoc, etc.) brings this home: requiring comments is as pointless as requiring lines-of-code or a minimum number of check-ins. The existence of comments adds nothing to source code; they make it harder to see the code itself and are often out of date.

/**
* this is the current record id
*/
public var currentRecordId : String ="";

/**
* handle search button click
*
* @param event the mouse event from the click
*/
private function searchButtonClickHandler(event : MouseEvent) : void
{
   ...
}

/**
* @return Foo
*/
public function get foo() : Foo
{
    return _foo;
}
/** TODO: fix this
*/
public function clearGlobalList() : void
{
    this.globalList.removeAll();
}
/**
* @param control int
* @param clearAll delete extra items
*
* @return the number of deleted items
*/
public function truncateData(maximumCount : Number) : void
{
    ...
}

A bad comment is worse than no comment. The goal is to add information to the source code, nor obsolete noise, and the best way is to name the variables, objects, and methods so they are self-descriptive. As you can see from the examples above, adding ASDoc headers makes the code less readable, and the names of the variables and functions already completely describe their behavior.

Good Nomenclature is the Best Comment

or

“The proper use of comments is to compensate for our failure to express ourselves in code.” — Robert C. Martin

“If the code and the comments disagree, then both are probably wrong” —attributed to Norm Schryer

“Good code is its own best documentation. As you’re about to add a comment, ask yourself, ‘How can I improve the code so that this comment isn’t needed? ‘ Improve the code and then document it to make it even clearer” –Steve McConnell Code Complete

I’m not advocating Hungarian notation. The need to use short variable names has long past, and abbreviating types is more than silly. Perhaps it is a dogged remnant of my sordid past in Pascal: I like complete, explicit names.

  • Class names should be specific nouns and avoid words that have meanings in the context of programming (we are running out of terms for “object”!). For example,
  • Method names should start with a verb (“open”, “delete”, “calculate”) and contain the names of the classes they are going to act on, e.g. importDetail(aDetail : Detail) : void
  • Property and field names should not include their class name (no Client.clientName) unless necessary to differentiate it within the context of the class (Client.clientName and Client.accountName).

Sample Naming Patterns

  • function findFoo(criteria) : Foo returns a Foo or null/-1/empty string if not found. I use an “a” prefix on my parameters to differentiate them from local variables and class fields/properties
  • function getFoo(criteria) : Foo returns a Foo or throws an exception if not found
  • function createFoo(initial data) : Foo returns a new Foo and adds it to the list/collection/model. Throws an exception if the Foo cannot be created (e.g. the key data already exists)
  • function openFoo(initial data) : Foo returns an existing Foo that matches the data or returns a new Foo and adds it to the list/collection/model
  • function removeFoo(aFoo) : Boolean returns true if aFoo was remove and false if aFoo was not present to remove. throws an exception is aFoo was there but the method could, for some reason, not remove it
  • function calculateTotal(fooArray : Array) : Number returns a value based on the parameter. The name indicates that the result is a dynamic value that is not stored persistently and is not based on anything else
  • function composeErrorMessage(error : Error, data : Foo, user : User) : String returns text value based on the parameters. The name indicates that the result is a dynamic value that is not stored persistently and is not based on anything else
  • class DeletionConfirmationView (not DeleteView or event DeleteConfirmationView). “Delete” is a verb and indicates a function (which is going to delete something). The view is going to present a confirmation dialog for the deletion (the noun form of “delete”).
  • function foo(param : type, pleaseDoSomething : Boolean) : void The second parameter is asking the method to do something like delete child objects, suppress notifications. The please makes it clear that it is a parameter, not a field or property of the object. Calling it doSomething or even isDoSomething does not make it clear that it is a parameter

Some bad examples from the Flex framework itself:

  • property includeInLayout, visible, includeInLayout – it should be “isIncludedInLayout”.
  • properties visible and enabled are at least adjectives, not verbs.
Other bad examples
  • property countFavorites – it should be favoritesCount. The function that calculates the value might be called “countFavorites()”

An excellent book referencing the code aesthetics of various luminaries is Clean Code, Robert C. Martin, Prentice Hall 2009, ISBN 0-13-235088-2

There, There, and Everywhere

While Flash is a full participant in the world and idioms of the web, Flex is more attuned to applications (e.g.  full-screen) rather than as part of a larger web page. I come from a traditional applications development (sometimes I say that I don’t do dancing kitties”). When Adobe made the AIR runtime for the major desktops, I felt like I was home. Just as Flex and Flash allow one to Write Once, Browse Everywhere, AIR allows us to write applications that behave the same (mostly) whether running off a browser or on a desktop1.

AIR is a desktop runtime container that executes swf applications2 stored on a local drive rather than receiving the swf as part of a web page in a browser. It’s runtime library supports several classes that the Flash Player runtime library does not, specifically ones dealing with local file selection and management, HTML display, windowing, and native chrome (menus, window widgets, etc). AIR also includes installation and update protocols useful for desktop applications, which include an application profile specifying who distributed  it (i.e. who digitally signed it) and if it will modify local files, access local resources like web cams, etc. The AIR runtime will enforce these limitations (just as the Flash Player limits its swf’s’ access to servers based on the server’s crossdomain.xml file).

Even with the new ability to package, install, and execute native code modules, AIR is not designed to build low-level system tools for the desktop. It is designed to present the same sort of rich application that the Flash Player presents on the browser. These application present data in interesting ways. They connect different services together (e.g. Twitter and Google Maps). They connect to private servers and databases.

Why AIR?

We want to offer an AIR version of our applications because of the things they will notice: They will notice if your web application does not have an internet connection. The will notice if they have to browse to every file instead of dragging it. They will notice that your application reminder makes a new tab in their browser instead of a toaster message onto their desktop.

The key to offering the same application on both the Flash Player and the AIR desktop is more than reuse the same pieces; the key is to “reuse” the whole thing.

To do this, create an AIR project and a Web (Flash Player) project (e.g. DoSomthingAIR and DoSomethingWeb). Both will have just the top-level application MXML file and an implementation of IFilesManager appropriate to that environment. The majority of the application is in a core component in a DoSomethingLibrary project. It  has all the data connections and UI of the application. It can use local storage3 to keep non-confidential default settings (and even share them between the Flash Player and AIR applications on the same machine).

The only parts of the application specific to AIR or the Flash Player are:

  • Native drag and drop messages are ignored in the player (but they generate standard drag & drop messages)
  • System connectivity messages (AIR only)
  • User inactivity messages (AIR only)
  • File access operations (AIR only)

If the core application component is listening for AIR-only events, it will still run well in the Flash Player (although it will never hear those events). To handle the differences with file access operations, for example, one can create an Interface that hides the details and have an implementation class for each platform (see AIRFileManager and FlashFilesManager in Figure 1). Each application can instantiate the appropriate instance and assign it to a property of the core application component or of some common static class. The core application calls methods of that property (which is typed to the Instance) oblivious to which platform’s class is doing the work.

Converting an Existing Application

One might have an application complete or near complete before one considers a dual platform deployment.It’s easy to break the core application out so both runtime platforms can use it.

  1. Open the existing project
  2. Create a new Library project
  3. Add any swc libraries (e.g. flexlib, a3corelib) that the existing project to the new Library project. You can move any swc’s from the original project’s lib/ to the new Library project’s lib/ as well
  4. Drag the src/com/company/stuff directories from the original project down to the Libraryproject src/. You want it to move, not copy.
  5. Open the project’s main MXML file and copy everything to the clipboard
  6. In the new Library project, create a new MXML component based on Canvas in the new library project. Call it “CoreApplication”
  7. In the new CoreApplication component, paste the clipboard under the <Canvas> element of the new element and remove the <Application> elements and any attributes that apply directly to the application itself.
  8. Save and build the new library project and fix any references.
  9. Add the library project to the existingproject’s Build Path. If you add the whole project instead of just the swc reference, debugging is easy
  10. In the existing project’s main MXML file, remove everything except the <Application> elements and those properties that apply only to the application itself (e.g. viewSourceURL)
  11. In Design Mode, add an instance of the new CoreApplication component from the Custom branch of the component tree. Set the bounds to: 0, 0, 100%, 100%
  12. Build the original application again. It should work exactly the same.

Now you can create a new project for the other runtime platform (e.g. AIR) and put a CoreApplication component in it as well.

Two-For-One Is Enough

This technique allows us to deliver the same application via a browser or a desktop; it does not magically change the application. Mobile applications are fundamentally different in their presentation and flows; although the delivery mechanisms (AIR and the Flash Player) might be the same, do not try to leverage any non-trivial application’s UI into a very different environment. For this, we do need to design the parts of the application for individual reuse in a new application designed for one or more mobile environments.


If you are new to AIR, a good intermediate book is:

Adobe AIR in Action, Lott, Joseph; Rotondo, Kathryn; Ahn, Samuel; Atkins, Ashley, Manning 2009


1Windows, Mac, and Linux desktops
2As well as HTML and JavaScript
3using the SharedObject class

Telescope to Hell, or An ActionScript Builder Pattern

One of the evils that OOP freed us from was long parameter lists like this:

wm_op(hdl, 0, 0 , 230, false, false, "false", true, ptr.value)

Even with default parameters and the occasional enumeration, telescoping parameter lists like these are chronic bugs waiting to happen and to regress. The problem was that call was not self-explanatory. Using object properties allows us to see each property’s name as we assign it:

var processor : Processor = new Processor(this);
processor.x = 0;
processor.y = 0;
processor.minHeight = 230;
processor.buttonText = "false";
processor.initialValue = pointer.value;

Instead of entering dummy arguments to allow access to later parameters, the object sets its own defaults.

Every Value a Parameter

The Every-Value-A-Parameter (EVAP) style of constructor design seems to forgo much of the strength of objects. It treats objects as data structures and does not take advantage of their properties’ ability to be internally consistent. The EVAP style passes all the internal values of the object in the constructor’s parameters, and all properties are read-only from that point forward (i.e. an immutable object).

If several parameters in a long list interact with each other or are mutually exclusive, either the constructor fails to create the object (often an opaque exception) or we do not check the interaction until needed (e.g. until a query object was activated). We cannot validate the parameters one-by-one because they all come in at once.

The calling code must also have all the information about the object at once.

var foo : Foo;
if (ref.gah >= 14)
   foo = new Foo(this, ref.gah, null, (container == null) ? null : container.bar);
else
    foo = new Foo(this, 2, null, (container == null) ? null : container.bar);

As shown, a symptom of  EVAP is a mass of trinary expressions (exp ? true : false)  in call parameters, or branches with alternate initializers for the same object. If one could set the new object’s attributes explicitly and individually (i.e. after it was instantiated), then the code branches would be specific to the attributes they affect.

var foo : Foo = new Foo (this);  

if (ref.gah > 14)
   foo.gah = ref.gah;
else
   foo.gah = 2;

if (container != null)
   foo.bar = container.bar;

A subtler aspect is the ability to allow descendant classes, containers, or helpers to override an object’s configuration. For example, a base query object might have a base query string, but a descendant class or a wrapper class, OracleSQLQuery, might take advantage of Oracle-specific syntax or settings. If the query string must be a read-only constructor parameter, the descendant cannot override an contained object created by its ancestor; at best, it can create a new object, copy every other attribute value, and assign it to a protected reference that the ancestor will (we hope) use.

Special Mutators for Mutually Dependent Properties

Some parameters’ validity depends on other parameters (e.g. height and minHeight). An object can adjust one to fit another, but this can violate a  object’s agreement with the user: a writable parameter value will be what the user set it to.

form.height = 95;
form.minHeight = 80;
...
form.height = 75;
form.minHeight = 70;

If the object unilaterally and silently changes the second value for height to 80 (the minimum), the coder will expect it to be 75. If the object rejected the assignment because it (at the time) violated the minHeight value, then the object will remain internally consistent.
Some properties are mutually dependent, so it is more than a matter of the sequence of assignment. If the object cannot defer the dependency validation (see below), then it can offer a special mutator-like function that accepts both or all of the mutually dependent values at once. Two or three parameters are not too obtuse, especially if the function names them explicitly.

foo.setNameAndPassword(...)
foo.setPosition(x, y);

Deferred or Explicit Validation

A SQLQuery object can allow any value for its queryText and parameters properties until the moment its active property turns true. At that moment, all of the properties must be consistent with each other (i.e. the items in the parameters collection must match the references in the queryText). If something tries to change one of these values in an active query, the object must decide whether to set active to false or to reject the new value (e.g. by throwing an exception).

Another example might be a class URIString, which does not check for validity until something calls function isValid(). The user can set and clear different, mutually-exclusive parts of a URI without raising an exception because their interrelations don’t matter until the validation method runs.


Jeffrey Stylos and Steven Clarke: “Usability Implications of Requiring Parameters in Objects’ Constructors.”ICSE 2007.

Immutable Objects and Internal Consistency

Nevertheless, some objects really want to be immutable. It saves a lot of checking and binding events, allows static caching, and removes the need for a .copy() or .clone() method.

The best of both wolds is an immutable object with a (mutable) builder. The builder object takes all of the initial values as interactive, public properties, optionally validates those values when they are set or just before the builder becomes the immutable constructor’s sole parameter. One might use it like this:

    var builder : Object = ImmutableObject.createBuilder();
    builder.name = "Fred";
    builder.birthMonth = 4;
    builder.birthYear = 1960;

    var imm : ImmutableObject = builder.create();

The immutable class and the builder class work together:

  1. The class’ static function returns an instance of the builder class
  2. The consumer plays with the builder’s properties
  3. The consumer has the builder create an instance of the class
  4. The builder validates its properties
  5. The builder passes itself to the class’ constructor
  6. The class initializes its immutable properties (i.e. the private fields) from the builder’s properties
  7. The builder passes the new class instance to the consumer

Instead of creating a public builder class for each immutable class and ending up with lots of little class files, we can use an internal class with some casting. Note that while the client code does not have access to the ImmutableObjectBuilder class, it gets an instance of that class (into its Object-type variable), and it cannot treat it like a generic object (e.g. builder.height = 44; gives an error).

public class ImmutableObject
{
    public function ImmutableObject(builder : Object)
    {
        if (builder is ImmutableObjectBuilder)
        {
            builder.validate();

            initialize(ImmutableObjectBuilder(builder));
        }
        else
            throw new Error("use ImmutableObject.createBuilder().create()");
    }

    private function initialize(builder : ImmutableObjectBuilder) : void
    {
        _name = builder.name;
        _address = builder.address;
        _birthDate = new Date(builder.birthYear, builder.birthMonth);
        _photoUrl = builder.photoUrl;
    }

    public static function createBuilder() : ImmutableObjectBuilder
    {
        return new ImmutableObjectBuilder();
    }

    public function get name() : String
    {
        return _name;
    }
    private var _name : String = "";

    public function get address() : String
    {
        return _address;
    }
    private var _address : String = "";

    public function get birthDate() : Date
    {
        return _birthDate;
    }
    private var _birthDate : Date;

    public function get photoUrl() : String
    {
        return _photoUrl;
    }
    private var _photoUrl : String = null;
}

class ImmutableObjectBuilder
{
    public var name : String = "";
    public var address : String = "";
    public var birthMonth : int;
    public var birthYear : int;
    public var photoUrl : String = null;

    public function validate() : void
    {
        if ((name == null) || (StringUtil.trim(name) == ""))
            throw new Error(""name" is required");

        if ((birthMonth == 0) != (birthYear == 0))
            throw new Error("Both birthMonth and birthYear must be set");
    }

    public function create() : ImmutableObject
    {
        return new ImmutableObject(this);
    }
}

The downside to this pattern is that it is a little tricky to subclass.[EXPAND Click to see how]
Using the ImmutableObject shown above, the descendant class has to get an instance of the ancestor’s builder and give that reference to its builder. The descendant builder cannot descend from the ancestor build because they are both internal classes.

The descendant builder has to proxy or shadow all of the ancestor builder’s properties so the descendant builder can use its reference to the ancestor builder to initialize the ancestor part of the descendant instance. I said it was a little tricky.

In this example, the descendant builder proxies properties (e.g. name, address) to the ancestor builder’s properties, and adds one new one: role.

public class Descendant extends ImmutableObject
{
    public function Descendant(builder : Object)
    {
       if (builder is DescendantBuilder)
       {
           builder.validate();

                   // this calls the ancestor's initialize()
           super(builder.ancestorBuilder); 

                 // we have to cast because the parameter 
                 // cannot be the internal class DescendantBuilder
           initialize(DescendantBuilder(builder));  
        }
        else
            throw new Error("use Descendant.createBuilder().create()");
    }

    public function get role() : String
    {
        return _role;
    }
    private var _role : String;

    //  we can't virtualize this method because
    //     we won't have access to the AncestorBuilder
    private function initialize(builder : DescendantBuilder) : void
    {
        _role = builder.role;
    }

    //      static methods are not inherited, so we do not override
    public static function createBuilder() : DescendantBuilder
    {
        var ancestorClassName : String = getQualifiedSuperclassName(Descendant);
        var ancestorClass : Class = Class(getDefinitionByName(ancestorClassName));
        var ancestorBuilder : Object = ancestorClass.createBuilder();

        return new DescendantBuilder(ancestorBuilder);
    }
}

class DescendantBuilder
{
    public function DescendantBuilder(ancestorBuilder : Object)
    {
        _ancestorBuilder = ancestorBuilder;
    }

    public function get ancestorBuilder() : Object
    {
        return _ancestorBuilder;
    }
    private var _ancestorBuilder : Object;

    public function get name() : String
    {
        return _ancestorBuilder.name;    //    proxy
    }

    public function set name(value : String) : void
    {
        _ancestorBuilder.name = value;
    }

    public function get address() : String
    {
        return _ancestorBuilder.address;    //    proxy
    }

    public function set address(value : String) : void
    {
        _ancestorBuilder.name = value;
    }

    public function get birthMonth() : int
    {
        return _ancestorBuilder.birthMonth;    //    proxy
    }

    public function set birthMonth(value : int) : void
    {
        _ancestorBuilder.birthMonth = value;
    }

    public function get birthYear() : int
    {
        return _ancestorBuilder.birthYear;    //    proxy
    }

    public function set birthYear(value : int) : void
    {
        _ancestorBuilder.birthYear = value;
    }

    public var role : String = null;    //    NOT a proxy

    public function validate() : void
    {
        _ancestorBuilder.validate();

        if ((role == null) || (StringUtil.trim(role) == ""))
            throw new Error(""role" is required");
    }

    public function create() : Descendant
    {
        return new Descendant(this);
    }
}

And the obligatory sequence diagram: 

[/EXPAND]

The Dark World of IExternizable

I never worked with Remote Objects much; I stuck with SOAP, REST., and AMF. What I did learn was how custom objects can represent themselves to an AMF stream, and to local-storage SharedObjects and fileStreams too.

ActionScript has built-in serialization (compatible with java.io.Externalizable interface). While this is very obvious streaming data over AMF pipelines (to LCDS, AMFPHP, Zend, etc.), it quietly makes saving and restoring data pretty painless. These operations use the streaming protocol:

  • RemoteObjects
  • Streaming objects to ByteArray.writeObject()
  • SharedObject (local storage)
  • EncryptedSharedObject

Simple Streaming

Most values and object will stream to and from AMF just fine. To effect this simple protocol, put the [RemoteClass("com.company.application.section.ClassName")] metadata tag (Flex projects only) above the class declaration so the parser knows what class to create. The class constructor must have defaults for all its arguments (or no arguments), and all public properties must writable (i.e. they must be vars or have mutators — aka “setters”).

The streamed properties that are the ones that are public var or have both a public accessor and a mutator. If a class has public properties one does not wish to stream, mark those properies with the [Transient] metadata tag.

[RemoteClass("com.company.application.section.Foo")]
public class Foo 

    public var name : String = "";
    public var id : String = "";

    [Transient]
    public var contact : Contact = null;
}

The streaming system streams and object in by creating a new instance and then setting each property in turn (it will not use the constructor’s parameters).

Streaming Read-Only and Private Properties

If some properties don’t have public mutators (i.e. they are publicly read-only), or one wants to stream non-public attributes, one can write custom serializing and de-serializing routines by implementing the interface IExternizable. It requires two methods:

[RemoteClass("com.company.application.section.Foo")]
public class Foo implements IExternizable
{
    public var name : String  = "";

    public function get id() : String
    {
        return _id;
    }
    private var _id : String = "";

    public function readExternal(input : IDataInput) : void
    {
        name = input.readObject() as String;
        _id = input.readUnsignedInt();

                // this object might need to be IExternizable too
        _contact = input.readObject() as Contact;
    }
    public function writeExternal(output : IDataOutput) : void
    {
        output.writeObject(name);   //  same sequence as readExternal()
        output.writeUnsignedInt(_id);
        output.writeObject(_contact);
    }
}

The IDataInput has no information about its data, so one cannot, for example, test to see if an integer value is less than 127 and safely call writeByte() instead of writeInt() (to save space) because readExternal() has no way of knowing if it should call readByte() or readInt(). One can stream format and version information out first, and use that information to determine the format of the rest of the data when streaming it in (although this smacks of variable record types from Days Long Past). It’s much easier to always stream the same object types in the same sequence, even writing out some empty strings and nulls as placeholders when necessary.

Any class implementing IExternizable must explicitly stream all its data because the built-in streaming is disabled . Note that the example above will stream the entire nested _contact object out as part of the Foo object stream. If  Contact implemented IExternizable, it’s readExternal() and writeExternal() would handle its streaming too.

Streaming References

If a class contains a references to another object, one can stream out an id and resolve the id after it streams in. One can resolve that id into an object reference either explicitly when both the referer and the cross-reference (e.g. the list of all Contacts) are ready, or do it as a lazy-loading accessor:

[RemoteClass("com.company.application.section.Foo")]
public class Foo implements IExternizable
{
    public var name : String  = "";

    public function get id() : String
    {
        return _id;
    }
    private var _id : String = "";

    public function get contact() : Contact
    {
        if (_contact == null)
        {
            if (_contactId != "")
            {
//
// some mechanism to find the contact by Id; it can return null
//
                _contact = Contact.lookupId(_contactId);
                _contactId = "";
            }
        }

        return _contact;
    }
    private var _contact : Contact = null;
    private var _contactId : String = "";

    public function readExternal(input : IDataInput) : void
    {
        name = input.readObject() as String;
        _id = input.readInt();
        _contactId = input.readObject() as String;
    }

    public function writeExternal(output : IDataOutput) : void
    {
         output.writeObject(name); // same sequence as readExternal()
         output.writeInt(_id);

         if (_contact == null)
            output.writeObject(""); // placeholder
        else
            output.writeObject(_contact.Id);   // just the Id
    }
}

Adding IExternizable to Existing Objects

If you add IExternizable to an object that has been saved and will be retrieved, you need to read the stream in the same sequence (and don’t fail if some new property is not in the stream). You can determine the sequence of properties before adding the writeExternal() by creating mutators for all the public properties, and then debugging while an instance comes in.

See Adobe Documentation on IExternizable

Reuse … Your Brain

Components were supposed to save us; they were the silver bullet that would make code reuse actually work. The problem with reusing code is that it takes at least three times as much work to make a component that works in all cases rather than just the ones the component author had in mind, and no one wants to put the work in unless they are getting paid.

The fun part of components is figuring out the best level of encapsulation and making a piece that fits nicely into that spot. Testing, debugging, documentation, and validation are not (for most people) the fun parts. for components to be useful in more than one context, they have to be internally and externally consistent, they have to handle attribute changes in all possible combinations, and they have to handle external error conditions at every possible point. Software libraries and SDK’s distribute themselves as classes and components, and they make applications possible. For the infrastructure organizations and component vendors, this is their business.

Components built within organizations do not have the support of paying users, and so they tend not to have the fit and finish of their commercial brethren. A commenter named Tim put it well in a discussion about Agile/XP and reuse:

The first time you have to pay for it to be coded,
The second time you have to pay for it to be reusable,
The third time it’s free.

With all due respect to Agile and XP, I err towards the other end of the spectrum: I like to build software clean enough that I am not embarrassed to have others use it. I want it so obvious that I will understand it quickly when I come back to it later. I like building well-rounded components that will survive a little transplantation or changes in usage. I like to take the time to make classes that know how to clone, clear, deep-copy/assign, and test equality. In other words:

Treat Yourself As You Would Have Others Treat You

Nevertheless, managers see a component named DataManager and assume (or at least hope) they can reuse it anywhere their design calls for a data manager. They don’t want to “waste” the effort spent building it the first time. Here is when intuition fails us all: we talk of “building” software instead of “composing” it. Software is ideas made manifest (albeit in a structure that judges those ideas against a very solid and unforgiving reality).  Software is not an engine where the number of cylinders is fixed. However, composing a better component is easier than building a second house. It’s often impossible to rebuild a component exactly the same as its original because the composer/author/developer/coder can’t stop themselves from improving their idea.

Besides running the same code in different environments, the best reuse is reusing experience. Experience grows all the time (and grows faster from bad outcomes). Rather than looking at components as commodities that remove the need for experienced developers, look at components as the steps that developers can stand on to see farther.

Teach Me, Bicycle-Repair Main

I finally have my car fixed. It is a 2005 Prius (second series) and would sometimes fail to allow the headlights to go into low-beams only. My mechanic could not find the cause and sent me to another mechanic. They spent several hours and determined that I needed a new (expensive) headlight switch, which they would special-order.

They estimated one (1) hour installation and I arraigned to bring the car in before work to wait while they installed it. When I arrived, they said it would be done in 1.5 hours. Hmmm.

Two hours later, I was on my way (late to my morning meeting). They cheerfully explained that they had never done this type of switch before, and that I would not have to pay for the extra time it took them. I snarled under my breath at their presumption that I should be happy that I did not have to pay for them being late.

Until I realized that, as software developers:

  • We too give estimates based on the best-case scenario (and we believe it ourselves)
  • We too have our clients/employers pay for us to learn new things
  • And we do charge them if things take us longer then we said they would

Multiple Views Using a Message-Based Checkbox Pattern

Third in a series of five. This blog entry is part of my article in the Flash and Flex Magazine

The previous post showed how one can have an item renderer communicate with one of its containers to set and retrieve the selected (e.g. checked) state of the item renderer’s data. If, however, the same data (and its selected state) appear in more than one view, one needs to add another set of notifications to the pattern.

If something other than a particular item renderer changes the values in the thingieList, the item renderer needs to know to change the checkbox status. Rather than iterating through the children of the DataGrid or List to find all the ItemRenderers to tweak them, we can have sort of a “push” notification: the item renderer passes a listener function to the list manager the first time it asks for an item’s selected status, and external changes call that listener. To make things as generic as possible, the listener does not expect any specific type of event (i.e. the event does not contain information about the change); it simply checks its own status whenever it’s called.

This combination seems complicated, but it’s built on what we’ve done before:

  • The view dispatches an AmISelected event with a reference to its event listener function in it.
  • The list controller adds the event listener
  1. Something changes the list
  2. The list dispatches a CHANGE (or COLLECTION_CHANGE) event to all the listener functions
  3. The view listener functions dispatch an AmISelected event (without a listener reference in it)
  4. The list controller received the AmISelected event object and sets its .isSelected property based on the list
  5. The item renderer checks the .isSelected property and updates its display based on the answer


This causes a lot of events that don’t actually find any changes (i.e. every item renderer whose data have not be selected or deselected), however the cost for these events is low and the value of simplicity is high.

The item renderer registers a listener the first time it checks its data’s status:

 ...
        var theEvent : ThingieEvent = new ThingieEvent(IS_THINGIE_SELECTED, true);
        theEvent.thingie = data.thingie;

        theEvent.notificationListener = this.onExternalThingieChange; this.dispatchEvent(theEvent); // ---- listeners execute here

        isThingieSelectedCheck.selected = theEvent.isSelected;
 ...

And the item renderer’s listener function checks the status

private function onExternalThingieChange(event : Event) : void
{
    var theEvent : ThingieEvent = new ThingieEvent(IS_THINGIE_SELECTED, true);
    theEvent.thingie = data.thingie;
    this.dispatchEvent(theEvent);
    isThingieSelectedCheck.selected = theEvent.isSelected;
}

On the list manager side, it adds the callback function (if present) as a listener using weak references. It could add the callback as a listener directly to the data list or to a separate IEventDispatcher object if it was going to fire events explicitly

private function onIsThingieSelected(event : ThingieEvent) : void
{
    event.isSelected = (_thingieList.getIndexOf(event.thingie) != -1);

    if (event.notificationListener != null)
        _thingieList.addEventListener(CollectionEvent.COLLECTION_CHANGE, event.notificationListener, false, 0, true);
}

By adding one notification, changes to the selection list automatically update all items whether they are visible or become visible later, so the user can can modify or clear the list without tight coupling with all the other views that add and remove items.

(Update: sample application in the final installment)

The Ultimate Checkbox List Pattern

Second in a series of five. This blog entry is part of my article in the Flash and Flex Magazine

A common task is to put checkboxes into a list or grid. Instead of adding Boolean property values to the dataProvider items, the Ultimate Checkbox List Pattern leaves the display item alone (e.g. a pure value object) and uses membership in a separate list of items to indicate if an item is selected (checked). Often, this list of selected rows itself is very useful. Standard ActionScript events communicate between the item renderers (with a checkbox) and a container object or the form itself acting as a controller for the selected list.

The key to this pattern is anonymous communication: the list controller does not know what components are sending messages asking if this or that object is or is not selected, and the view (i.e. an ItemRenderer) does not know who is listening and answering its questions. They communicate using a custom event that adds a reference to the item, and a Boolean: isSelected. For example,

public class ThingieEvent extends Event
{
    public var thingie : Thingie;
    public var isSelected : Boolean = false;
    public var notificationListener : Function;
}

Changing the Selected State
The ItemRenderer sends an event when user interaction with its checkbox changes the selected state:

 ...
        var theEvent : ThingieEvent = new ThingieEvent(THINGIE_SELECTION, true);
        theEvent.thingie = this.data.thingie;
        theEvent.isSelected = thingieCheckBox.selected;
        this.dispatchEvent(theEvent);
 ...

The list manager might handle the event like this:

    private function onIsThingieSelected(event : ThingieEvent) : void
    {
        var existingIndex: int = _thingieList.getIndexOf(event.thingie);
        if (event.isSelected != (existingIndex != -1))
        {
            if (event.isSelected)
                _thingieList.addItem(event.thingie);
            else
                _thingieList.removeItemAt(existingIndex);
        }
    } 

    private var _thingieList : ArrayCollection = new ArrayCollection();

Getting the Selected State
When an ItemRenderer initializes itself, it needs to know if it should set the checkbox.selected attribute based on the data. It needs to ask someone outside itself if the current item should be checked. Rather than have the list manager add event listeners to every ItemRenderer, the ItemRenderer dispatches an event, waits for all the listeners to review it , and look at the event’s properties as the answer to the question.
It dispatches an event that bubbles (or is proxied up to the DataGrid or List) to some container acting as a list manager. It will set the event.isSelected property. Once the dispatchEvent() method returns, the ItemRenderer looks at that property.

 ...
    var theEvent : ThingieEvent = new ThingieEvent(IS_THINGIE_SELECTED, true);
    theEvent.thingie = data.thingie;

    this.dispatchEvent(theEvent); // ---- listeners execute here

    isThingieSelectedCheck.selected = theEvent.isSelected;
 ...

Note that after the .dispatchEvent(), the event has whatever value the listeners put in there. On the list manager side, the listener might look like this:

    private function onIsThingieSelected(event : ThingieEvent) : void
    {
        event.isSelected = (_thingieList.getIndexOf(event.thingie) != -1);
    }

Note that it does not cost anything to add a listener more than once, and using a weak reference prevents memory issues. The Ultimate Checkbox List Pattern uses bubbling events; if one is not fond of them, one can proxy the events through custom Column classes, then through the top-level Grid or Listbox, and then up to whatever is acting as the list manager.

An advantage to bubbling events is immunity to changes in the number of containers between the item renderer and the list manager. One can even encapsulate some set of containers into a component and embed it in another container without changing this pattern.

The Ultimate Checkbox List Pattern has several advantages over using a flag in the dataProvider item to persist checked status:

  • The dataProvider items can remain pure value object (e.g. unchanged from an loosly-linked data module)
  • The same item can have separate selection-states on an infinite number of lists
  • The list of selected items is always current and available at a high level; one does not need to iterate through the dataProvider items
  • Items remain selected even when they are not visible or if they are not in the dataProvider’s collection. One can page off and back and previously selected items are still selected.
  • Items can be selected and deselected across several different views (if the list manager tests membership using an ID instead  of object identity). E.g. one can have browse lists and search results that reflect each other’s selection (ee the next posting for details).

(Update: sample application in the final installment)