Wednesday, July 8, 2009

Dumb mistakes.

Here are a couple of mistakes I make after a long day of coding. Can you spot the errors?

1. Stack Overflow


public class Person
{
private var _name : String;

public function get name() : String
{
if ( name == null ) name = "anonymous";
return _name;
}

public function set name( value : String ) { _name = value };
}


The problem: run this code and you'll get an output panel full of "stack overflow" errors. Why? Well, take a closer look at the getter method. It's supposed to return the value of private member "_name". But the first statement in the method refers to "name," not "_name" (note the underscore). _name is the private member; name is the getter method.

When the first statement executes, it tests to see if THE OUTPUT OF THE GETTER METHOD ITSELF is equal to null. Remember, when you type the name of a getter method by itself, you're really just using a syntactic sugar. "name" is really "name()." So what I'm doing in the first statement is similar to this:


function foo() : Number
{
if ( foo() == null ) trace( "x is equal to null" );
}


The call foo() in the first statement calls the function foo, which has a call to foo in the first statement, which calls foo... and so on. An infinite recursive loop.

In the previous example, I can remove the loop by simply adding underscores to "name":

bad: if ( name == null ) name = "anonymous";
good: if ( _name == null ) _name = "anonymous";

Now name is not calling itself; it's referring to a private member called _name.


2. Null Envy


var herName : String;
var flower : Sprite;
var sheLovesMe : Boolean;
var herAge : Number;
var kisses : int;

if ( herName == null ) herName = "Lisa"; //works like a charm

if ( flower == null ) flower = new Sprite(); //works like a charm

if ( sheLovesMe == null ) sheLovesMe = false; //error

if ( herAge == null ) herAge = 18; //error

if ( kisses == null ) kisses = 0; //error


The problem here is that Booleans and numbers types can NEVER be set to null. They don't accept null as a value; nor can they be compared to null.

Once you define a Boolean, it is automatically set to false. (You can later change its value to true.) There's no such thing as a Boolean with no value, though you can set a Boolean to undefined.


var iLikeCheese : Boolean; //note: not explicitly set to a value
trace( iLikeCheese ); //false


You also can't set or compare a Number to null. Unset numbers are set by default to NaN, which is short for "not a number." However, you can't do this:

if ( herAge == NaN ) herAge = 18; //error

Instead, you have to do this:

if ( isNaN( herAge) ) herAge = 18; //works like a charm

ints and uints default to zero. If I'm using an int as a uint -- in other words, if my int should never be set to a negative number -- I sometimes set it to negative one by default. For instance, you can't give a girl a negative kiss, so...


public static const NOT_SET : int = -1;

var kisses : int = NOT_SET;

if ( kisses == NOT_SET ) kisses = 10;


For this reason, I often use ints to store hex-color values. How else should I indicated no color? After all, zero is black. I suppose I could use a uint and define something like this:


public const NO_COLOR : uint = uint.MAX_VALUE; //MAX_VALUE is a built-in constant

var favoriteColor : uint = NO_COLOR;

if ( favoriteColor == NO_COLOR ) favoriteColor = 0xFF0000;


This solution is probably good enough for most simple circumstances, but if I need something more robust and scalable, I create a class:


public class Color
{
public static const NO_COLOR : uint = uint.MAX_VALUE;
private var _color : uint = Color.NO_COLOR;

public function get color() : uint { return _color; }
public function set color( value : uint ) { _color = value; }
public function isSet() : Boolean { return _color == Color.NO_COLOR; }
}

looping through a class's static members

How do you loop through all static members of a class?

First of all, why would you want to do that? Well, let's say you're writing a game in which the player can move in the four classic compass directions:


public class Directions
{
public static const NORTH : String = "north";
public static const SOUTH : String = "south";
public static const EAST : String = "east";
public static const WEST : String = "west";
}


Somewhere in your game, you have a moveInDirection() method that accepts a direction. But you want to make sure it doesn't try to move the player in illegal directions, e.g. moveInDirection("up"); The IDE should prevent this, because if you type moveInDirection(Directions.UP) you'll get an error (because there's no UP constant).

However, I'd like to make moveInDirection a bit more idiot proof than having it rely on the IDE. Also, it's possible that directions may be chosen at run time. For instance, a player might type a direction in a textfield, as in a text-adventure game. What if the player types "up"?

So I'd like moveInDirection() to check if the player is trying to make a legal move...


function movieInDirection( direction : String ) : void
{
if ( isLegal( direction ) )
{
...
}
}


The question is, how should isLegal() work? The last thing I want to do is to use a bunch of conditionals or an Array...


function isLegal( direction : String ) : Boolean
{
var legal : Array = [ "north", "south", "east", "west" ];

for each ( var legalDirection : String in legal )
{
if ( direction == legalDirection ) return true;
}

return false;
}


That's a terrible solution, because it couples the class Directions to the Array in my isLegal function. Scaling will be dangerous. For instance, what if I add a new constant to Directions...

public static const INSIDE : String = "inside";

... but forget to add it to the Array?

var legal : Array = [ "north", "south", "east", "west" ]; //Oops! Forgot to add "inside"

A better solution is to loop through all the constants in Directions and check if the player's attempted direction exists. But how do you loop through all the static members of a class? After playing around with arcane solutions involving prototype chains, I settled on using the little-known describeType() function. It's in the flash.utils class, and you import it like this:

import flash.utils.describeType;

If you feed describleType() the Directions class -- trace( describeType( Directions) ) -- it outputs an XML description of the class:


<type name="Directions" base="Class" isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<constant name="WEST" type="String"/>
<constant name="NORTH" type="String"/>
<constant name="EAST" type="String"/>
<constant name="SOUTH" type="String"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="Directions">
<extendsClass type="Enum"/>
<extendsClass type="Object"/>
</factory>
</type>


It's then a fairly easy matter to parse the xml, extract all the constants, and test them against the player's choice. I packaged the solution in a utility class:


package com.grumblebee.constants
{

import flash.utils.describeType;

public class Utilities
{
public static function isLegal( enumClass : Class, value : String ) : Boolean
{
var xml : XML = describeType( enumClass );
var xmlList : XMLList = xml.child( "constant" );
var enumName : String;

for each ( var child : XML in xmlList )
{
enumName = child.attribute( "name" ).toString();
if ( enumClass[ enumName ] == value ) return true;
}

return false;
}

}
}


I can't shake the feeling that there's a better way to do this. I'd love to lose the XML parsing. But this is the best I can come up with for the moment. One thing I could do is transform the player's string to upper-case and test it directly to see if there's such a constant in Directions:

if ( Directions[ playerString.toUpperCase() ] != undefined ) ...

But that only works if I stick to the convention of NORTH = "north". It fails if Directions looks like this:


public class Directions
{
public static const NORTH : String = "n";
public static const SOUTH : String = "s";
public static const EAST : String = "e";
public static const WEST : String = "w";
}


it would also fail in the case of...

public static const UNDER_THE_BRIDGE : String = "under the bridge";

At one point, I thought about adding the isLegal() function to Directions. You can get a class to refer to its own static constants this way:

trace( prototype.constructor[ "NORTH" ] ); //north

Sadly, though prototype.constructor allows you to access individual class variables and constants, for some reason, you can't loop through its members:

for each ( var s: String in prototype.constant ) trace( prototype.constant[ s ] ); //no output

It also doesn't work if you explicitly name the class:

trace( Directions[ "NORTH"] ); //north
for each ( var s : String in Directions ) trace( Directions[ s ] ); //no output.

So until something better comes along, I'm stuck with XML parsing.

Saturday, June 6, 2009

ditch conditionals; use factories

When I first started coding, I used a lot of switch/case statements and complex ifs. But over the years, I become suspicious of them. Now, when I feel the urge to reach for a switch/case, I slap my wrist and try to come up with a better construct.

To demonstrate the problem, I've come up with a toy example: an app that fills the stage with little Fisher-Price-type people.



There are two types of people, bald people and hairy people. Just before placing a person on the stage, my app randomly chooses if he's going to have hair or not. Bald people are all members of the Person class; Hairy folks are members of the HairyPerson class. To create such classes, I do this:

var person1 : Person = Person( new bald() );
var person2 : Person = HairyPerson( new hairy() );

Note that I type both sorts of people to Person. I can do that because HairyPerson is a subclass of Person (and subclasses can be typed to their parent's type). By giving the vars the same type, I can pass them both into functions that expect a Person type, and those functions will work regardless of whether the person is a Person or a HairyPerson.

What are those new bald() and new hairy() calls doing for me? bald and hairy are MovieClips in my FLA's Library. Person classes must be passed a reference to a MovieClip. They use the clip as base artwork, which they then customize via random colors. If you want to know more about Person construction, you can check out my FLA and AS files, but the details aren't important to this post, so I won't elaborate here.

The question is this: in my Document class, where I randomly choose types of people, how do I instantiate type chosen at random? In the past, I would have done it this way:


for ( var i : int = 0; i < 100; i++ )
{
        rand = Math.floor( Math.random() * 2 );
        
        switch ( rand )
        {
                case 0 :
                        person = new Person( new bald() );
                        break;
                        
                case 1 :
                        person = new HairyPerson( new hairy() );
                        break;
                        
                
        }
        
        person.render();
        person.x = Math.random() * Stage.stageWidth;
        person.y = Math.random() * Stage.stageHeight;
        addChild( person );
}




The problem with this is that it doesn't scale well. If I add another type of person, say a HatWearingPerson, I need to add another case -- and I need to change my Math.random() statement so that it is range includes my new case:


for ( var i : int = 0; i < 100; i++ )
{
        rand = Math.floor( Math.random() * 3 ); //2 changed to 3
        
        switch ( rand )
        {
                case 0 :
                        person = new Person( new bald() );
                        break;
                        
                case 1 :
                        person = new HairyPerson( new hairy() );
                        break;
                        
                case 2 : //added
                        person = new HatWearingPerson( new hatWearer() );
                        break;
                
        }
        
        person.render();
        person.x = Math.random() * Stage.stageWidth;
        person.y = Math.random() * Stage.stageHeight;
        addChild( person );
}



This isn't such a big deal in my toy example, but imagine a more complex system in which you were constantly adding and removing types of people. Not only would I have to create the new classes; I'd also have to remember to add (or remove) new cases to the switch/case statement and to update the Math.random() statement. Eventually -- probably sooner rather than later -- I'm going to screw up and forget to add a case or forget to update Math.random().

But the bigger problem is that my Document class and the people classes are tightly coupled. Good OOP practice tells me that those person-instantiation statements shouldn't be hard coded into the Document class. Classes should be as independent from each other as possible, so that you wind up with a modular system in which you can change one class without having to change another.

What's the alternative? Factory classes! Factories are classes that make instances of other classes: Here are mine:


package
{
        public class PersonFactory implements IPersonFactory
        {
                public function getPerson() : Person
                {
                        var person : Person = new Person( new bald() );
                        return person;
                }
        }
}



package
{
        public class HairyPersonFactory implements IPersonFactory
        {
                public function getPerson() : Person
                {
                        var person : Person = new HairyPerson( new hairy() );
                        return person;
                }
        }
}



package
{
        public class HatWearingPersonFactory implements IPersonFactory
        {
                public function getPerson() : Person
                {
                        var person : Person = new HatWearingPerson( new hatwearer() );
                        return person;
                }
        }
}



As you can see, these classes all implement an interface called IPersonFactory. You'll see how this helps me out in a second. In the meantime, here's the interface:


package
{
        public interface IPersonFactory
        {
                function getPerson() : Person;
        }
}



My new and improved Document class looks like this:


var person : Person;
var rand : int;
var factories : Array;

addFactory( new PersonFactory ); //see addFactory(), below
addFactory( new HairyPersonFactory );
addFactory( new FancyPersonFactory );

for ( var i : int = 0; i < 100; i++ )
{
        rand = Math.floor( Math.random() * factories.length );
        person = factories[ rand ].getPerson();
        
        person.render();
        person.x = Math.random() * stage.stageWidth;
        person.y = Math.random() * stage.stageHeight;
        addChild( person );
}
                        

function addFactory( factory : IPersonFactory ) : void
{
        factories.push( factory );
}



Note that the addFactory function accepts any class that implements the IFactory interface, so my Document class doesn't know -- or need to know -- how many types of people (or people factories) exists.

From now on, if I add a new Person subclass, I just need to make a factory for it and pass that factory to my the Document class.

Friday, June 5, 2009

visual test toolkit

I'm a big fan of the Flash player, the SWF format and the Actionscript language, but I'm not crazy about the Flash IDE. It belongs on the B-list of many categories.

Want an animation tool? Check out After Effects (or Toon Boom Studio). Flash is a light-weight by comparison. Want a vector-drawing app? Use Illustrator (especially now that it has the Blob Brush!). Want a coding IDE? Use Flex or FDT. Flash dips its toes into many pools but refuses to dive into any of them.

However, I do find Flash useful for one thing -- so useful that I start it up at least once a day: Flash is a faux command-line interpreter for Actionscript! It's not really an interpreter, of course. It's more of a compiler. But it beats everything else for quickly trying out a bit of Actionscript. You don't need to create a project, a class or even a function. Just throw some code on the timeline, press Command+Enter and Bob's your uncle. That's a terrible way to code anything real, but it's a great way to quickly test out a bit of functionality.

Sometimes, when I'm doing these tests, I need visual elements. And I waste time creating little circles, square and text fields. So I quit doing that. Instead, I created a little testing file that I use over and over. It's got a stage full of doodads and whatnots, and everything is labeled with its instance name. Also, items in the library have Export for Actionscript turned on, so I can create new instances with code if need be.

I leave this file open all day, with frame 1 of the timeline exposed in the AS editor. If I need to run a quick test, I'm all set to go.

Here's the file.

Tuesday, June 2, 2009

generating getters and setters

I'm down with OOP and using getters and setting instead of exposing class member variables, but making getters and setters is a pain. Flex and FTD have tools to help automate the process, but they don't automate it enough. I wanted to be able to type in a list of vars like this...

private var _newWidth : Number;
private var _newHeight : Number;
private var _scaleList : Array;
private var _moveList : Array;
private var _oldWidth : Number;
private var _oldHeight : Number;
private var _widthPercentChange : Number;
private var _heightPercentChange : Number;

... and, via a single click, get this...

public function get newWidth() : Number
{
return _newWidth;
}

public function set newWidth( value : Number ) : void
{
_newWidth = value;
}

public function get newHeight() : Number
{
return _newHeight;
}

public function set newHeight( value : Number ) : void
{
_newHeight = value;
}

public function get scaleList() : Array
{
return _scaleList;
}

public function set scaleList( value : Array ) : void
{
_scaleList = value;
}

public function get moveList() : Array
{
return _moveList;
}

public function set moveList( value : Array ) : void
{
_moveList = value;
}

public function get oldWidth() : Number
{
return _oldWidth;
}

public function set oldWidth( value : Number ) : void
{
_oldWidth = value;
}

public function get oldHeight() : Number
{
return _oldHeight;
}

public function set oldHeight( value : Number ) : void
{
_oldHeight = value;
}

public function get widthPercentChange() : Number
{
return _widthPercentChange;
}

public function set widthPercentChange( value : Number ) : void
{
_widthPercentChange = value;
}

public function get heightPercentChange() : Number
{
return _heightPercentChange;
}

public function set heightPercentChange( value : Number ) : void
{
_heightPercentChange = value;
}

And now I can, because I built a little AIR app to do it for me. I can copy in the private vars, press the GENERATE button, and -- BINGO! -- out pops my getters and setters. Then I can click the COPY button, which copies the getters and setters to the clipboard. Finally, I can paste them into Flex or FDT.



Here's a link to the app.

Notes: it is template-based, so if you don't like the code it generates, it's easy to make it do what you want. Click HELP for more info.

Also, please note that though this is a useful tool, it can be abused. For instance, some properties should be read only. They shouldn't have a setter. So use with caution and good OOP practices!

keeping up with the actionscript joneses

I use an RSS reader called Vienna to keep up with Actionscript news. Over time, I've compiled a big list of AS-related blogs, which I've now published as in opml file. Feel free to download it an import it into Vienna (File > Import). I'll update the opml when I find new feeds.

Monday, June 1, 2009

mac apps

I work on a mac. Here are the apps I use in my work. I'll update this list when I start using new apps or quit using old ones.

MEDIA
Vlc. This is a one-stop-shop video player that plays virtually any format.

WRITING
Textmate. The best text editor I've ever found for the Mac.

MacVim (free). The old Unix editor wrapped with a Mac GUI. Edit code without touching the mouse.

Open Office (free). Open-source MS Office replacement.

TextExpander. Allows you to make system-wide keyboard shortcuts that expand into blocks of text. For instance, on my system, typing aaaa expands to my complete mailing address. You can set up shortcuts that work only in specific apps.

Slidepad. Neat little text-editor that slides on and off the screen via a keyboard shortcut. I used it for on-the-fly, temporary notes.

INFO MANAGEMENT
Evernote (free). A fantastic app that lets you keep track of any sort of information. It can sync to multiple computers, the web, and many mobile devices (including the iPhone).

APP LAUNCHING
Namely (free). Allows you to launch any Mac app via the keyboard. It's a lightweight alternative to Quicksilver, which always bogs down my system.

LauncherConfig (free). Launches multiple files at once. I use it every morning to launch iChat, my mail client, my svn client, my ftp client and my Twitter client with one click.

WEB BROWSING
Firefox Browser (free). I await a Mac version of Google Chrome.

Firebug (free). THE must-have Firefox plugin for web developers.

Fluid (free). Allows you turn web pages into stand-alone apps. I use it so that I can easily launch gmail into its own window.

DEVELOPMENT
Flash Builder 4 (formerly Flex Builder). This is my main coding tool. I used to use FDT, which is terrific, but Flash Builder has now outgunned it. Flash Builder is the best AS (and MXML) editor out there.

Aptana Studio (FREE). A one-stop show IDE for HTML, CSS, Javascript, Python, Ruby and PHP. It's Eclipse-based.

MAMP (free). An Apache server for the Mac.

RegExp Tool (free). This is the best app I've every found for testing out Regular Expressions.

DESIGN
Adobe CS4 Suite. Of course.

REMOTE FILE MANAGEMENT
Transmit. My FTP client of choice. It allows you to edit files while they're online.

Syncro SVN Client. Full-featured GUI client for the Mac.

Zumodrive (free for 1GB, $ for more). A virtual harddrive that you can access from anywhere.

Transmission. Solid bittorrent client.

SOCIALIZING
Colloquay (free). All-you-need IRC client.

Tweetie (free if you use add-supported version). Solid Twitter client for the Mac (and iPhone).

EMULATING
Virtual Box (free). Run Windows on the Mac. Like Parallels, but free.

READING
Vienna (free). RSS reader with a build-in Browser.

Tofu (free). Paste text into this cool tool, and it formats the text into narrow columns, which makes online reading much easier. It's the closest you'll get to a Kindle on your computer screen.

MISC
Eigenclock (free). Replacement for the system clock. Includes a dropdown calendar.


Caffeine
(free). Lets you temporarily disable sleep, so that your monitor doesn't power down. Useful if you're watching a long video.

Default Folder X. I seriously don't know how I lived without this. It wraps open, save and save-as dialogs inside a feature-packed window containing shortcuts to folders you need to access quickly. You can define any shortcuts you want.