Making ActionScript Look Beautiful: Increasing Readability and Loosing Verboseness

After playing around with languages such as Ruby and Groovy, I’ve been yearning to loose a lot of the verboseness of ActionScript. I feel that many languages tend to be overly expressive, and hide the concepts of what your code is actually doing.

Lets take a simple example of a snippet of code that represents, Is tomorrow after today?

function isTomorrowAfterToday():Boolean
{
    var now:Date = new Date();
    var today:Date = new Date(now.setHours(0, 0, 0, 0));
    var tomorrow:Date = new Date(now.setDate(now.date + 1));
    return tomorrow.getTime() > today.getTime();
}

To me this is bloated, confusing and unreadable. Creation logic is obfuscated and not DRY. Variables are created to represent common concepts, and comparison operators are used that don’t represent the real domain. However, this is how I see most code in ActionScript written. It is the path of least resistance to getting your project done. Most languages are like this and give you the lowest levels of the API, without providing any means to working with them easier. Why not give the developers a proper toolkit to make this more sensible?

So lets try cleaning it up:

function isTomorrowAfterToday():Boolean
{
    return Date.tomorrow().isAfter(Date.today());
}

See how much better that is. So what have we done here?

  1. First, we’ve consolidated the creation logic (Date.tomorrow() and Date.today()), and they belong to the class they represent. Not only is it readable, but it’s DRY.
  2. Second, we’ve taken the greater than operator and made it into a method, Date.isAfter(). Is tomorrow greater than today? No! Dates have no concept of greater than or less than.
  3. Third we’ve removed accessors that return the primitive data that the class uses to store state. Why should my code have to know that Date.getTime() returns the primitive data used to compare dates? To selfishly put it; the only thing my code should care about is to ask the question, Is tomorrow after today?

Let’s take it one step further:

import flash.date.tomorrow;
import flash.date.today;
 
function isTomorrowAfterToday():Boolean
{
    return tomorrow().isAfter(today());
}

Getting closer. So what have we done? Well, we’ve taken the concept of creation, and have moved it once again. Creation can be generalized into the package of which the main class it represents. In this case, the Date class can be given it’s own package flash.date.

Taking it another step further:

import flash.comparison.is;
import flash.date.tomorrow;
import flash.date.today;
 
function isTomorrowAfterToday():Boolean
{
    return is(tomorrow().after(today()));
}

Perfect! Again, so what have we done here? We’ve abstracted the concept of equality into it’s own package. We can express other concepts of comparison such as not().

Like so:

import flash.comparison.is;
import flash.comparison.not;
import flash.date.tomorrow;
import flash.date.today;
 
function isTomorrowNotTheSameAsToday():Boolean
{
    return is(tomorrow().not(today()));
}

Lets take a whole different concept, such as distance, and model the simple question, Is 10 feet farther than 5 feet?

import flash.comparison.is;
import flash.distance.Distance;
import flash.imports.use;
 
function is10FeetFartherThan5Feet():Boolean
{
    use(Distance);
    return is((10).feet().fartharThan((5).feet());
}

You might be asking yourself, “Is this really ActionScript?” The answer is yes, and can be accomplished with the use of ActionScript’s Object.prototype static property. Again what is all of this doing?

  1. First, we’re telling our function that we’ll be using classes and methods for distances. This acts like an import statement, and adds prototype methods to Flash’s Number class.
  2. Second, we’re creating distances based off of a number. When we call 10.feet() we’re calling a prototype method that we’ve defined on Number to return a Distance object of 10 feet. In English, this reads much nicer.
  3. Third, we’re reusing the concepts that we’ve established earlier. is() is an equality concept that we defined within the flash.comparison package. We’re using method names used to compare objects of the same type, Distance.fartherThan(). Lastly, we’re comparing the primitive values of an object, by not having to compare the values of both distances explicitly with call like Feet.value.

Many of the concepts are things you can start using today. Begin by adding reusable and readable comparison methods, such as Person.isOlder() or Person.isYounger(). It’ll increase the reusability of your domain and make it much more rich. Also, add and chain together static builder methods in your classes, i.e. var dan:Person = Person.thatIs().male().age(24).name("dan").

Happy coding, and keep it clean!