Wednesday, March 12, 2014

Why to avoid binding whenever possible?

Binding is one nice cool feature and it is used a lot and i really mean a lot!! We see that we get a collection (which is marked bindable mostly) of value objects where every value object is marked with RemoteAlias tag and Bindable tag. We change any of the property and it reflects. Isn't it cool? Yes it is but it comes with a serious performance issue.

Generally experienced programmers (Read it as experts) recommend to avoid binding as much as possible, if not entirely. This feature is overused, frankly. If we know that only 2 properties of the value object will change then making the whole value object bindable is overkill. When we mark the class with Bindable tag at top all its public properties become bindable which may not be needed all the time. It is better tom assign this tag to those properties that may change.

First of all avoid using Bindable it has serious performance problems if used a lot. It generates a lot of code which can have impact on performance. We can keep the value-objects in collection and can handle the job of updating the view manually. We can make use of itemUpdated() method to notify the view whenever the items change in collection. To keep track of changes in collection we can write a handler for collection change event. We should also avoid calling refresh() on array-collection until and unless we really need as this also is a performance problem.

Lets consider the following example taken from this presentation:

package valueObject

{

  [Bindable]

  public class Product {

    public var productName:String;

  }

}




This code generates a hell lot of code:

package valueObject
{
  import flash.events.IEventDispatcher;
  public class ProductManualBinding implements IEventDispatcher
{
private var dispatcher:flash.events.EventDispatcher = new flash.events.EventDispatcher(flash.events.IEventDispatcher(this ));
    [Bindable(event="propertyChange")]
public function get productName():String {
return _productName;
}
public function set productName(value:String):void {
        var oldValue:Object = _productName;
if (oldValue !== value) {
_productName = value;
dispatchEvent(mx.events.PropertyChangeEvent.
createUpdateEvent(this, "productName",oldValue,value));
}
    }
public function addEventListener(type:String,listener:Function,
useCapture:Boolean= false, priority:int= 0, weakRef:Boolean=false) :void 
{
      dispatcher.addEventListener(type,listener, useCapture,                 priority, weakRef);
}
public function dispatchEvent(event:flash.events.Event):Boolean
{
return dispatcher.dispatchEvent(event);
    }
public function hasEventListener(type:String):Boolean
{
return dispatcher.hasEventListener(type);
}
public function removeEventListener(type:String,
listener:Function, useCapture:Boolean = false):void 
{
        dispatcher.removeEventListener(type, listener, useCapture);
    }
public function willTrigger(type:String):Boolean
{
return dispatcher.willTrigger(type);
}
  }
}
First thing it generates a lot of code. Second thing we can observe is to specify the name of the event in Bindable tag is a good practice. That also has performance impact. The various scenarios are considered here.

If we really need binding then better option is to set binding using BindinhUtils class and get hold of change watcher. When we feel we don't need binding anymore we should remove it immediately by calling unwatch() method using the change watcher instance.

If we think carefully we will observe that most of the times we can skip binding. There are some common misuses of bindings explained in the link.

Also check: How to remove binding on an object?

No comments: