Friday, June 24, 2011

Smalltalk Immutability: Builder Pattern

In this blog post I will show a means to enforce immutability of Smalltalk objects. This is provided by constructing a builder for the intended object which initialises the particular object. An initialisation flag is set after construction to guarantee that the object accessors do not mutate the state after this point.

There are multiple sources on the internet which explain the benefits of immutable objects. Notable examples are:

In Smalltalk instance variable are only visible to the object they belong to. Not even an object of the same class can access them. So in potential Smalltalk objects can truly be immutable.
But this (in)visibility of instance variables poses a problem. How can one create an immutable object with prescribed values for the instance variables?
While pondering this question I came up with the following solution.

In "Design Patterns: Elements of Reusable Object-Oriented Software" the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides) describe the builder pattern.
The builder pattern allows a client to configure all the relevant properties of an object prior to construction. This goal is reached by introducing a helper object which is responsible for recording the preferred properties and is used in the construction of the object.

We will use MyObject class in our examples. The MyObject class has an instance variabe myVariable, which should be initialized to false. We wil now transform this class into a truly immutable object.
Enhance the MyObject class with a new instance variable initialised. For each instance variable, change the getter as follows:

MyObject >> myVariable
  initialized ifFalse: [ 
    NotInitialisedException new signal
  ].
  ^ myVariable
Where NotInitialisedException is a custom exception class.
Furthermore, for every instance variable, create a one-time setter as illustrated below.
MyObject >> myVariable: value
  initialized ifFalse: [
    myVariable := value
  ]
The combinations of getter, setter and initialised instance variable make sure that all instance variables can be set only once, if the initialised instance variable is set to true after construction. This will be the responsibility of the MyObject class.

A new class method should be introduced.

MyObject class >> newFrom: builder
  | o |
  o := MyObject new.
  o initialiseWith: builder.
  ^ o
MyObject's initialiseWith: method should set the initialised instance variable to false after all the instance variable are retrieved from the builder.
MyObject >> initializeWith: builder
  initialized ifFalse: [
    myVariable := builder myVariable.
    initialized := true
  ]
I have omitted the code for the builder class. It should have accessors (and backing instance variables) for each instance variable of MyClass. The instance variables of the Builder should be given sensible defaults so that a client does not have to configure a lot prior to construction of a new object.

This wraps up the example of an immutable object in Smalltalk with the help of the builder pattern. It provides a way to force immutability on Smalltalk object by introducing a strict way of accessing instance variables and a record of initialisation state.

Wednesday, March 30, 2011

Syntax Highlighting for Smalltalk

In discussions about software it is nice to show code. It can drive an abstract point home by giving an example.

I have some experience with Alex Gorbatchev's SyntaxHighlighter. It is a javascript based syntax highlighter with customizable brushes. The downside: no Smalltalk brush.

So I set out to create a Smalltalk brush for SyntaxHighlighter. The git repository SyntaxHighlighter-Smalltalk-Brush holds the result. As a test case I used the Smalltalk syntax on a postcard example. You can see an example below.

exampleWithNumber: x
   "A method that illustrates every part of Smalltalk method syntax
   except primitives. It has unary, binary, and keyword messages,
   declares arguments and temporaries, accesses a global variable
   (but not and instance variable), uses literals (array, character,
   symbol, string, integer, float), uses the pseudo variables
   true false, nil, self, and super, and has sequence, assignment,
   return and cascade. It has both zero argument and one argument blocks."

   |y|

   true & false not & (nil isNil) ifFalse: [self halt].
   y := self size + super size.
   #($a #a "a" 1 1.0)
    do: [:each | Transcript show: (each class name);
          show: ' '].
   ^ x < y
 

Monday, March 28, 2011

@smalltalkgalore Compendium

This blog is a compendium to @smalltalkgalore, a twitter stream devoted to smalltalk.

Sometimes 140 characters is not enough to express a certain view or explain a certain point. Whenever that happens you can find a blog post on the subject here.