21.2.13

Lazy Evaluation

If you've ever worked with Flex Components you will know by heart what lazy evaluation is, as it is a big dogma streching across all components. But lazy evaluation is pretty common and usefull in all kinds of applications. The idea is to delay calculations/operations till the moment you actually need them done.

A simple example is instantiating when accessing the object:
public function myObject():Object
{
 if ( this.myObject == null ) this.myObject= new Object();
 return this.myObject;
}
This can be very useful in case your object is costly to create or you rarely access it and want to avoid lots of unused objects. But you can push this concept further and for example delay entire state changes and object updates by just setting a flagging it as invalid and once you end up using your object validate it.

Flex is full of it and you read a lot of invalidate() validate() and see validation flags all over the place. You might change lots of entries at the same time that are displayed on a completly different and currently inactive page. It would be a waste to update that list whenever an entry changes unless the list is actually visible. Even then you only want to update it once, right at the end of your operation or even later, just before the displaylist gets it time to update and refreshes.

I currently used this lazy approach in my 3D programming experiements. Rotations in 3D space are a tricky and calculation intensive thing to do, but Quaternions are a great way to deal with them. The downside is that any other aspect would rather like to calculate with a simple 4x4 Matrix representing the rotation, scale and translation of the object. Its easy to transform from one coordinate system to another using matrices and also graphic hardware uses matrices for the 3D projection.
/**
 * invalidate matrix when position, rotation or scale changes
 */
private function onComponentChange( event:Event ):Void 
{    
 this.invalidMatrix = true; 
}

/**
 * returns the transformation matrix; validates in case of previous changes
 */
public function getMatrix():Matrix44 
{
 if ( this.invalidMatrix )
  this.validate();
 
 return this.matrix ;
}
Using lazy evaluation I can guarantee that I only perform the necessary quaternion to matrix conversion and matrix multiplications when required, but work with my quaternion directly as much as I please.

In reality you just reverse the order of performance load to reading instead of writing. So you have to make sure you rather write a lot instead of reading when using this method. Especially when using native getter/setter like: a.lazy++; which is a read and write access in disguise.

It took me a while to get my head around this (especially when I was first working with Flex) and I certainly introduce some more uncertainty when debugging but I think it has its fair share of benefits.

No comments:

Post a Comment