Hints on Smalltalk Style

Here are a few suggestions on writing Smalltalk programs with good style. These are by no means comprehensive!

Comments, Variable Names, Indentation

As in any programming language, include useful comments and use descriptive variable names. Since Smalltalk doesn't include type declarations, some programmers like to use names such as anArray or aStream for variables to give a hint as to what kind of object is expected. This has no significance for the Smalltalk compiler, though.

Use indentation consistently in your methods. Make methods short -- typically two browser panes worth of text at most. (Generally the style in Smalltalk is to make methods shorter than the typical C or C++ procedure.) If you do end up with a method that keeps getting longer and longer, define some private auxiliary methods, and then just invoke then using (for example) self helperMethod.

Instance variable, argument, and temporary names should start with a lower-case letter; global and class variables with an upper-case letter. Unfortunately, underscore isn't a legal part of identifiers in Smalltalk, so use capitalization to separate words, e.g. aVeryLongInstanceVarName.

Using the Inheritance Hierarchy

It is almost always a mistake to write code that tests for the class of an object. For example, suppose you're writing a simulation of a pinball machine. You might have classes for different gadgets in the pinball game, such as flippers, blackholes, bumpers, and so forth. Suppose that you're now writing the code that decides what to do when the pinball runs into one of the gadgets, which is bound to a variable 'gadget'. Don't write something like the following in the Ball class:
gadget class = Flipper ifTrue: [...].
gadget class = BlackHole ifTrue: [...].
Instead, turn this around and send a message to gadget so that flippers and black holes can respond differently:
gadget hitByBall: self
Then you can define different versions of hitByBall: in Flipper, BlackHole, and so forth.

If you really need to know whether an object obeys some message protocol, define a method to ask. For example, all objects in Smalltalk understand isNumber. Numbers return true, everything else returns false.

Control Structures

Study the rich set of looping methods available for collections (do:, collect:, and so forth) - and use them.

Unfortunately the syntax for conditionals in Smalltalk makes nested conditionals hard to read. You can judiciously use ^ (return) to improve readibility. Consider the sign method for Numbers, which returns -1, 0, or 1 depending on whether the number is negative, zero, or positive.

Here is a version using nested conditionals:

sign
   ^ self < 0 
      ifTrue: [-1] 
      ifFalse: [self > 0 ifTrue: [1] ifFalse: [0]]
Compare with:
sign
   self < 0 ifTrue: [^ -1].
   self > 0 ifTrue: [^ 1].
   ^ 0
The sign method isn't too bad, but it gets worse with more complicated logic. Sometimes it's worth writing an auxiliary method just so you can return from the middle of the auxiliary method to make the code clearer. (Remember ^ pops out of nested loops, conditionals, etc.)

Global Variables

Generally, avoid referencing global variables, except for class names and a few variables defined in the system, such as Transcript or Sensor. An exception is when you're doing some quick-and-dirty experiments - in that case it's sometimes handy to store an object in a global variable. But if you don't need the object again, it's better to use a temporary variable to hold it. You can declare and use temporaries in a workspace, for example:
  | s |
s := Stack new.
...
Often it's more appropriate to use self or a message to a class in place of a global variable. For example, in Smalltalk the color yellow is obtained by sending the message 'yellow' to the class color, rather than by storing it in a global variable.
Color yellow
Similarly, the constants pi and e are found in Smalltalk by sending messages to Float:
Float pi
Float e
Or here's a questionable example from the Smalltalk haikus the 505 students wrote some years ago:
i ride a turtle
into object nirvana
evan become: nil
A haiku in better Smalltalk style would have been:
i ride a turtle 
into object nirvana
self become: nil