Monthly Archives: June 2010

Or That

Coming from Delphi, I use properties for everything. I even create protected and private properties for use inside a class:  they are good idea, so I don’t limit them to public interfaces.

A new wrinkle I’m dealing with is bound properties that have default values. For example, a Button sub-class that has a default caption but also has a public property that the user can bind to some other value. A normal property with a default would look like this:

private static const DEFAULT_ENABLED_CAPTION : String = "Click me!";

[Bindable]
public var enabledCaption : String = DEFAULT_ENABLED_CAPTION;

One can bind this property to a child component in an MXML component or use it in the commitProperties() method of an ActionScript component. It acts as a proxy for the “real” property, and allows different values based on state (e.g. enabled and disabled captions based on the enabled property).

When one uses binding to set values, if the object configuration is null or the property enabledCaption is blank at any time, the property loses its default value and does not get a valid replacement.

    <components:MyButton enabledCaption="{configuration.enabledCaption}"
                  disabledCaption="{configuration.disabledCaption}" />

Assuming that one does not want to allow an empty string (or null), some small changes to the accessor and mutator can handle these automatic assignments by the binding mechanisms:

public static const CAPTION_CHANGE : String = "captionChange";
private static const DEFAULT_ENABLED_CAPTION : String = "Click me!";

[Bindable(event="captionChange")]
public function get enabledCaption() : String
{
    if (_enabledCaption== "")
        return DEFAULT_ENABLED_CAPTION;
    else
        return _enabledCaption;
}
public function set enabledCaption(value : String) : void
{
    if (value == null)
        _enabledCaption = "";    //  strings should not be null

    if (_enabledCaption != value)
    {
        _enabledCaption = value;
        this.dispatchEvent(new Event(CAPTION_CHANGE));
    }
}
private var _enabledCaption : String = DEFAULT_ENABLED_CAPTION;

No matter how many times the binding mechanism updates the component property (i.e. calls the mutator), the accessor will return the default value unless the binding (or some other code) sets the value to a non-null, non-blank string.

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

Advanced Topics Using a Message-Based Checkbox List Pattern

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

The checkbox pattern described in the previous four blog entries allows a lot of flexibility and subtly in your applications. This post covers some of the issues I’ve dealt with, a bit of philosophical and aesthetic musing, and an example application.

Setting The Manager’s Event Listeners

Setting the  list manager’s listeners in the startup event cycle is tricky. In general, I use addEventListener() in the creationComplete event for listeners on the form, however this does not work if the checkbox list or grid is a design-time  child on the form (e.g. it’s in the MXML or created by createChildren()). By the time the creationComplete event fires, the grid has already initialized and all the item renderers have dispatched their first AmISelected events, which receive no answers because the listener is not set up yet.

Register amISelected listeners in the initialized event.

Messages vs. Interfaces

A different way of loosely linking parts of a system is interfaces. One could pass an instance of an interface that had toggleSection and amISelected methods to an item renderer. The class of that instance could be anything; the caller would not know who was executing the method and the method would not know who was calling it. Passing an instance more than one layer deep, however, creates a loosely-linked chain, and the more links in a chain, the more fragile it is.

Every container between the list manager (e.g. the form or component’s top-level container) would have to pass the instance on to every child that could hold it (probably because the children implemented an interface themselves). Components that had no interest in this interface would still be responsible for passing it on.

Messages, however, are already part of every UIComponent’s interface (because it implements IEventDispatcher): they allow listeners to hook into the messages; the message framework moves the event objects through the containership model; and the event objects themselves can change without changing the interface.

Message-Based MVC

The Ultimate Checkbox List Pattern resembles a Model-View-Controller: the item renderer would be the view; the list of selected items would be the model; and the event listeners on the list manager would be the controller. In an classc MVC pattern, the controller would push the changes into the view, and therefor would need to know how it worked (i.e. what method to call or property to push). The UCLP has the model pushing a change notification into a generic listener in the view, and then the view pulls the change information from the model; the module (and the controller, for that matter) do not know anything about the view besides a reference to the view’s notification listener.

Matching By Value vs. Matching By Reference

As shown in the sample application, one can use a more robust test to see if a Thingie is in the selected list than simply checking getIndexOf(). While the “thingie” might be a complex Value Object, this pattern also lends itself to simple data objects that might be dynamically created to wrap one or two column values. In this case, the object itself might not come from a global (i.e. singleton) store; one might have several simple instances that represent the same values, but not the same instances in memory.

For example, in the sample application (which has View Source)

 

Sample Message Based Checkbox List Application
click for SampleMessageBasedCheckboxListApplication

 

the AmISelected method checks if the data is selected, not just if the Thingie instance in the event is also on the list. Actually, the original version had a middle section that used api.business.gov to show a grid that was not even Thingie objects, but it has no crossdomain.xml, so…

Use this pattern to support your needs: if you have different representations of the same concept and you want to select or de-select the concept, then make the AmISelected check if the concept is on the list; if the objects in question are references to singleton objects on a central list (e.g. value objects), then check if the object itself is referenced by the list.

Let Me Know

Let me know what you think of this pattern. Let me know how I could explain it better. How have you improved it ?