Learning to K.I.S.S (part 1)

State management is something that all developers must tackle, from building complex multi-player games to RIA’s to micro games.  State is constantly changing and the way we deal with that could determine the success or failure of a project and certainly the amount of firefighting (bug fixing) to get the project into a releasable state. Immutability is a tool for managing state with an application; immutable objects are objects that do not change state beyond initial construction. The title of this post, ‘Learning to K.I.S.S’ (keep it simple stupid), describes an important benefit of immutable objects; they will greatly simplify your application.

  • Objects which are immutable are predictable, programmers can be assumptive about an object because of its encapsulated final state.
  • An Immutable object clearly shows the intent of the programmer, an immutable Tween object, for example, in a Tweening API describes a clear and direct transfer of information to the tweening engine.
  • Objects which are mutable require more thought and design decisions relating to access rights and friendship amongst objects and so add complexity to systems.
  • An codebase which utilises the power of immutable objects will be safer; inexperienced programmers are protected against bad programming decisions, simply, because they are unable to make them.

In this two part post I will be discussing how we implement immutability for a variety of scenarios in Actionscript and using various techniques.  I hope that the examples will convince you of the benefits of striving for immutability in your objects where it is possible.

Starting at the beginning

So you’ve identified a need, and created a class, but you must give this class some state and set some data.  Unfortunately, unlike our brothers and sisters in the Java world, we are missing the ‘final’ keyword for variable declarations.  In Java the final keyword allows you to define a variable once, and only once.  Unlike constants in Actionscript, final fields can be declared after the variable declaration in the constructor which is incredibly useful in creating immutable objects.


/**
 *  An example illustrating how to create
 *  immutable objects in Java using the 'final' keyword
*/
public class Monster {

    final String name;
    final boolean isScary;

    public Monster(String name, boolean isScary) {
       this.name = name;
       this.isScary = isScary;
    }
}

These variables cannot be accidentally overwritten as they have already been set, any attempts to reset any of these variables would result in a compile time exception. In Actionscript we can declare our immutable field as constant or private, however each have their limitations. Constants are great if you know the value ahead of time, and this method of creating enumerated types in Actionscript is a great way of utilising that power. However in most cases you’ll simply want to declare your field private and set its state within the constructor. Private fields in Actionscript cannot be accessed or overridden by subclasses, so in many ways this provides some security, you are however not protected from yourself.  If your class accidentally sets a private field twice, it will not be obvious.

Managing state with Getters and Setters

It is common place to use setters to mutate private fields, however unless you are using the data transfer/ value object pattern (discussed further down), this is generally considered a bad idea. The problem with objects constructed with getters and setters is that objects do not have to be fully initialized.  This initialised state can be changed at any point in the application and is predictable. The broken encapsulation via public setters means that the object is open to abuse by friend objects. Objects that still want to provide this functionality but maintain some immutability use idempotent methods: the returned value will always be the same given the same input.  A setter will return a new object with the new value and cloned values from the parent. A good example of this technique is an immutable list. Calling a method add(objects) : * on an immutable list, will return a new list including the newly added object. The code might look something like:


public function add(value : *) : *
{
	checkNotNull(value, "cannot add a null value to the list");
	return new ImmutableList(value, this);
}

This idiom comes with a warning: setting up an object results in superfluous object creation and consequentially a strain on the garbage collector. However it is worth noting that this type of object creation would usually be part of setup and therefore not a big part of the application runtime.

A word on namespaces

One use for namespaces is to describe access rights between classes, in particular when those classes are between packages and access cannot be described using existing namepaces. Although namespaces cannot be used to create strict immutablity, they can be used to give contextual immutability:

Consider a parser and a model; the parser reads some data, creates and stores that in the model.  The parser is only used when more data is requested by a service.  The model contains a number of setters designed for use by the parser and allows the model to be build up over time (perhaps the data cannot be set at once, or there is too much data for the constructor). Defining a custom namespace between the parser and the model will describe an access intent and relationship between parser and model’s setter methods.

/**
* An example illustrating contextual immutability between a model and parser
*/
public class Monster {

    namespace SetMonster;

    private var name : String;
    private var isScary : Boolean;

    SetMonster function setName(name : String) : void
    {
        this.name = name;
    }
    //...etc
}

public class MonsterParser {

    /**note the :: syntax indicating we are using a namespace, for more info see
    *adobes http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/Namespace.html
    *returns a Monster object which is added to a list of Monsters stored in the app model
    **/
    public function extractData(data) : Monster
    {
        const monster : Monster = new Monster();
        monster.SetMonster::setIsScary(data.isScary);
        monster.SetMonster::setName(data.name);
        return monster;
    }
}

In this context a Monster is intended to be immutable because only the parser has access to the setters and a new Monster will be instantiated each time data is extracted; given another context and you are just defining access points. A gotcha with this pattern is that anyone can use a namespace as long as its known about/ documented.  If your API is packaged up chances are this namespace will remain unknown and it would take effort on behalf of a user of the API to find and abuse it.

Object construction

One of the most basic ways we can both pass state into our object and ensure its immutability is by using the constructor to pass arguments into our object. These arguments are used to initialize the state of the object by setting various private fields. This approach is fine given two or even three fields, but after that quickly becomes dirty. Multi parameter constructors are difficult to read once coded and make for a confusing API prone to error:

Imagine a constructor passing in several strings and ints, reading code which instantiates this object is difficult without the help of documentation or an intelligent code hinting system in the IDE: “which string is which, I can’t remember”, says the confused developer.

const testObj : TestObject = new TestObject('target1', 12, 'target2', 34, 'target3', 23, 'target4', 43, 0, 16);

A good rule of thumb is set by Robert Martin “When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own”. Some API’s try to get around the multi parameter constructor by accepting an object containing optional parameters such as TweenMax and Away3D. Constructing a tween in Away3D may look like :

var sphere:Object3D = new Sphere({material:"red#", name:"sphere", x: 300, y:160, z: 300, radius:150, segmentsW:12, segmentsH:9});

In my opinion this later approach is no better than the former.  You may have named parameters which makes object construction more descriptive, but the programmer will get no code completion from the IDE and is forced to continually refer to documentation (unless this programmer is a robot who has memorized the API by heart!).

Summary

In this post we have looked at some of the limitations of the language and  some of the most common object construction techniques.  In the next post we’ll be looking at other slightly more complex design patterns and idioms that attempt to create immutable objects whilst getting around some of the limitations of other techniques.

One thought on “Learning to K.I.S.S (part 1)

  1. Pingback: Learning to K.I.S.S (part 2) | The Mosh Pit

Leave a Reply