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

In the last post we discussed the importance of immutable objects in a code base and took a critical look at some common techniques for creating immutable objects.  In this post we’ll be looking at some design patterns/ idioms that try to get around those problems whilst still maintaining immutability.  I highly suggest reading the previous post, found here before continuing.

The Parameter/ Data/ Value Object (aka The Object of many names)

In the previous post we saw some problems with passing multiple arguments through in a constructor; that it is difficult to read and prone to error.  That code can be re-factored using ‘Introduce Parameter Object’ you can find more information on this in Martin Fowlers refactoring guide.

  1. Create a value object which temporarily holds all the values required to initialize your object.
  2. Pass this object into the constructor of your object
  3. Set private fields using the data object.
  4. Don’t keep a reference to the data object.

Note step 4: a common mistake would be to hold a reference to the value/ parameter object, however this would void your mutability because an external class could set values on the parameter object and make returned values unpredictable.

This technique is considered fairly expensive because with every new immutable object you must also create a value/ parameter object.  In addition this method does not hide away the implementation details like a factory would, however it can be used nicely in conjunction with a factory.  This pattern does encourage code reuse as VO’s can be pooled if they are frequently used, or using something like the flyweight pattern.

/**
* An example showing incorrect usage of the Value Object pattern
*/
public class MonsterController {

    private var monster : MonsterVO;

    public function MonsterController (monster : MonsterVO)
    {
        this.monster = monster;
    }
}

public class GameController {

    public function GameController()
    {
        const monster : MonsterVO = new MonsterVO();
        monster.setIsScary(true);
        monster.setName("trulyScaryMonster");

        new MonsterController(monster);
        monster.setIsScary(false); //not immutable, we've just set scary after construction!
    }
}

/**
* An example showing correct usage of the Value Object pattern
**/
public class MonsterController {

    private var name : String;
    private var isScary : Boolean
    public function MonsterController (monster : MonsterVO)
    {
         name = monster.getName();
         isScary = monster.getIsScary();
        //aha any changes to the monster object will not affect this class!
    }
}

The builder

The builder by name is designed for construction only and uses a fluent interface to build an object.  It abstracts complex construction logic and produces an immutable object once built. The pattern adds a layer of security to your code; input values may be validated before an object is constructed. In my opinion this is a better solution than a value object because of the incredibly descriptive interface and validation.

This pattern does not need to add superfluous code to the codebase; since the builder and its object are often tightly coupled, it is fine to create an internal class. The code below is based on the builder pattern described by Joshua Bloch in his book Effective Java. Note that actionscript does not support nested classes, (there are work arounds, see this interesting post!), we can however add classes within the same file and internal fields will be accessible by classes only within the same file.

package com.mindcandy.example.immutability
{
    public class Monster
    {
        private var name : String;
        private var isScary : Boolean;

        public function Monster(builder : MonsterBuilder)
        {
            name = builder.name;
            isScary = builder.isScary;
        }

        public static function getBuilder() : MonsterBuilder
        {
            return new MonsterBuilder();
        }

        public function toString() : String
        {
            return " test Monster: " + this.name + " is scary : " + this.isScary;
        }
    }
}

import com.mindcandy.util.preconditions.checkNotNull;
import com.mindcandy.example.immutablity.Monster;
class MonsterBuilder {
       internal var name : String;
       internal var isScary : Boolean;

       public function setName(name : String) : MonsterBuilder
       {
            this.name = name;
            return this;
        }

        public function setIsScary(scary : Boolean) : MonsterBuilder
        {
            this.isScary = scary;
            return this;
        }

        private function validate() : void
        {
           checkNotNull("name must be set for monster", name);
        }

        public function build() : Monster
        {
            validate();
            return new Monster(this);
        }
    }

Another nice builder style pattern is the Immutem pattern which also delays instantiation of an object until initialization parameters have been set.  In my opinion it is inferior to the builder as it lacks the fluent interface (a major advantage) of a builder.

The immutem pattern cannot be implemented in actionscript because the language does not support nested static classes.  A work around by including a private class in the same file (see example above) would still not work because the ‘nested’ class would not have access to the parents private fields. This pattern highlights some of the limitations of actionscript in comparison with older languages such as Java.

A criticism of these patterns are that they are great for code-generator tools but not so great for humans, I do however, tend to disagree with this statement as they add a great deal of value in terms of readability which far out-weighs the additional cost of maintenance (providing the construction is complex enough to warrant a builder).

Immutability via Bubble Wrap

A number of patterns can be used to wrap up your object in an protective bubble wrapped blanket of immutability.  These patterns are generally more flexible and can be coded to allow different access levels and permissions for the object.

The immutable wrapper interface wraps an object in an interface which provides only getters thus the object appears immutable.  I say appears because the fundamental weakness of this pattern is that objects may be upcast and then mutated.

public interface ImmutableWrapper
{
    function getGrowl() : GrowlType
}

public class MutableObject implements ImmutableInterface
{
    private var growl : GrowlType;

    function getGrowl() : GrowlType
    {
        return growl;
    }

    function setGrowl(growl : GrowlType) : void
    {
        this. growl = growl;
    }
}
//abuse of the interface
const immutableObject : ImmutableInterface = getWrappedObject();
(immutableObject as MutableObject).setGrowl(GrowlType.CHEEKY);

Patterns that deal with composition to filter access do not suffer from the same weakness as the immutable wrapper.  Both the proxy and decorator can be used to wrap a mutable object and limit access to fields, they are not immutable patterns as such, but control data access.  Both are able to control access to an object via composition, by storing a reference to the mutable object the proxy or decorator expose an api which can make decisions as to which method calls to foward to the object.  Note typically the decorator pattern would add responsibilities to an object, whereas the proxy would control access.

These particular patterns become a preferred choice when we are trying to limit mutability by controlling various access levels or mutating according to state.  The protection proxy pattern could control access by an agreed list of friends or by the current state of the application.

Consider a document where users have different access privilidges, i.e read-only, read-write, etc.

public final class DocumentProxy
{
    private var mutableDocument : Mutable;
    private var currentState : StateType = StateType.MUTABLE;

    public function saveText(text : String) : void
    {
        if(StateType.MUTABLE)
        {
            mutableDocument.addText(text);
        }
        else
        {
            application.displayWarning("you do not have write privilidges");
        }
    }
}

At this point we are starting to delve into access patterns which will control access to mutable objects, thus limiting mutability, however the objects are not immutable. Limiting mutability is still a good idea and can lead to high encapsulation, predictable state and cohesivness.  Its beyond the scope of this post to delve into those patterns, but examples include the proxy pattern, friendship and locking patterns where conditions prevent or grant access to an object, perhaps depending on a key or predefined friendship.

Frozen code

Popsical immunity describes an object which may continue to mutate until it is set to a frozen state; at this point the state is frozen to further mutations.  The object may have fields mutated multiple times until this state has set and may be useful in scenarios where we are building up a complex object involving multistage calculations (although usually here a builder would do). Popsical immunity could be achieved using the proxy pattern and would follow the following steps:

  1. Create a mutable object
  2. Mutate the values until required state is reached
  3. Create a proxy for the object
  4. Make the object available only via the proxy and throw away references to the original object

Another popular pattern explicitly sets a locked state and performs validation checks at mutating methods.  This code can be quite messy as the multiple checks can add a lot of noise to the code, although this could be abstracted to a helper method.  The following code is an example of how this check might be achieved, although for the purposes of brevity the null/ undefined checks are incomplete.  Other examples are more explicit in their checks and simply set a ‘frozen’ boolean field.

final class Monster
{
    private var growl : GrowlType;

    public function getGrowl() : GrowlType
    {
        return growl;
    }

    public function setGrowl(growl : GrowlType) : void
    {
        Popsical.setOrThrow(growl, value);
    }
}

//Immutable object helper class
public class Popsical
{
    public static function setOrThrow(property, value) : void
    {
        if(property.isNull)
        {
            property = value;
        }
        else
        {
            Log.warn("could not set property on immutable value + property + value");
        }
    }
}

Personally I don’t think this is a great way to enforce immutability and any of the afore mentioned patterns would be a better substitute.  This method would need very clearly documenting and is likely to confuse an API; how is the programmer to know that this object can be set only once? The implementation of this pattern could lead to either:

  • incomplete construction of objects via the example above
  • or, using the freeze method, objects which are not frozen due to a forgetful programmer creating a very difficult to trace bug.

Documentation

Revisiting the reason why we are striving for immutablity: we are trying to communicate, secure and protect the code by limiting state.  If for some reason immutability is unreasonable to implement or refactor then documentation can provide a fail safe.  Well documented code with descriptive methods can at the very least signal some author intent and warn against mutating an object.

/**
* @param growl this should really only be set once because ...
* TODO : refactor this class to be immutable
*/
public function setGrowl(growl : GrowlType) : void

Your documentation may not get read, but at least you tried!

Summary

Immutable objects won’t save you from every pitfall, but its a good place to start. Not all objects should be immutable : view objects being the first that springs to mind.  However thinking about the implementation of immutable objects should in the very least get you thinking about object encapsulation and SRP.  Code should feel simpler, cleaner and easier to read.

Our dev team prides itself on the simplicity of its code; any level of programmer can jump onto an area of the codebase and quickly start working.  In my opinion this is a worthy ongoing goal : let’s K.I.S.S!

The topics discussed in this blog post are an amalgamation of techniques and ideas discussed by various industry experts which I cannot take credit for, I heartily recommend the books listed below!

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.