Tuesday, November 30, 2010

Extending AS3 trace

On a previous post (debugging spaghetti code) I mentioned it's important to know where a specific function is being called.
From Adobe, this is the description of what the function trace does:
Displays expressions, or writes to log files, while debugging.
We can trace anything anywhere in our code, however, as mentioned before, how do we know where? we could then specify this in each trace call, for example:
trace('MyClass - ' + someValueToTrace);
trace('MyClass - ' + someOtherValue);
Right, instead of writing the object's name in every call, we could have a private function to do this:
private function debug(objectToTrace : Object) : void
{
trace('MyClass' + objectToTrace);
}
Then, instead of calling 'trace(blah)' we use 'debug(blah)' which will include the class name. For example:
debug(someValue);
// outputs: 'MyClass - someValue'
Advantages? well, if in case we don't want to trace anything any more, we just comment out the 'trace' line in our code rather than deleting every single call to debug in that class...

Cool! now we know where are we using 'trace'.

Can we extend it? sure thing! and this is my solution:

- Create a class in your utils package, name it Debug.as.
- Create a static function to trace the name of the caller plus any parameter.
Code:
package com.mysite.core.utils
{
import flash.utils.getQualifiedClassName;

public class Debug
{
/**
* // Writes in the flashlog the name of the object calling this function and any number of parameters

* Debug.print(this, someValue, someOtherValue);
*/
public static function write(caller : Object, ...arguments) : void
{
var objectString : String = getClassName(caller);
trace(objectString + ' - ' + arguments);
}

private static function getClassName(object : Object) : String
{
var className : String = getQualifiedClassName(object);
return className.slice(className.lastIndexOf('::'));
}

}

}
If we don't use the second function (getClassName), the output would be '[object MyClass]' so that's why we slice a string to get only the very class name.
Now you can call Debug.write instead of trace in the debug function on every class:
private function debug(objectToTrace : Object) : void
{
Debug.write(this, objectToTrace);
}
// use debug(objectToTrace) instead of trace(objectToTrace)
Sweet! :)

Friday, November 05, 2010

A poor man's Currency Formatter

*Title stolen from Arthur Debert Tweener tips.

While the Adobe flash.globalization package is still in beta, which includes a CurrencyFormatter class, we need to find a quick way to display an amount formatted as currency, with thousand separator and decimal mark.
In this case, we are targeting USA and UK so the thousand separator is a comma and the decimal mark is a point.
Right, so this is some simple logic used:
  • multiply the number by 100 to get the decimals
  • check if new number is zero or less than 100 (if less than 100 then is a decimal)
  • otherwise get the decimals and keep them aside
  • divide the rest of the number into groups of three and push them into an array
  • reverse the array and add the decimals
  • voila! you got the number formatted as currency!
So, yeah, the commas in that separate elements in the array work now as thousand separators :)
And here is the code:
private function formatCurrency(amount : Number) : String
{
var newAmount : String = String(Math.round(100 * amount));

if (newAmount.length == 1) newAmount = '0';

else if (newAmount.length == 2) newAmount = '0.' + newAmount;

else
{
var decimals : String = '.' + newAmount.slice(-2);
newAmount = newAmount.substring(0, newAmount.length - 2);

var amountGroup : Array = new Array();
while (newAmount.length > 3)
{
amountGroup.push(newAmount.slice(-3));
newAmount = newAmount.substring(0, newAmount.length - 3);
}
amountGroup.push(newAmount);
amountGroup.reverse();
newAmount = (Number(decimals) > 0) ? (amountGroup.join() + decimals) : amountGroup.join();
}
return newAmount;
}

Oh well, it does the job and as the CurrencyFormatter from Adobe is not implemented YET in pure AS3 (Flex Builder 4*), that code is useful :)

Salut!

*The CurrencyFormatter supported in Flex SDK 4.1 works with MXML only.

Thursday, November 04, 2010

Debugging spaghetti code

spaghetti-code

As a programmer, sometimes you find yourself dealing with this nasty badly written code and your task is to fix some even nastier and ugly looking bugs.

Whether is code you wrote yourself some years ago or someone else's (which makes it even worse) as it's your task to dig into the code, you will need help, help to understand where in heaven one of the dozens of public methods in that class is being called.

Yeah, in that code, almost all the methods in all the classes (including the main one) are public and of course is highly coupled making it almost impossible to read or to maintain.

Spaghetti code, hundreds of messy lines of 'code' (?) in each messy class... oh the joy...
After hours of work, after cursing everyone around you, you find the function which is causing the issue but... where is it being called? who's calling it? why?
Here it comes Stack Trace to the rescue! woohoo!
And the line of actionscript 3 that has saved me from cursing even the ones that are not around me is:

trace(new Error().getStackTrace());

That line will output in the flashlog the path (including class names, and code lines) that the thread takes before throwing the error (you will need flash player debugger to see the error). Now we now where the function is being called, time to continue debugging...

*Image taken from SpreadShirt.co.uk.