Performance aside, here are other by-products of the method lookup implementations we've been discussing. *Reflection*, Smalltalk's ability to examine and fundamentally alter its own semantics while it is executing, is impossible in the traditional compile, link, and execute world of C++. Moreover, the instantaneous (re)compilation of a Smalltalk method—Smalltalk's exploratory development gestalt—is possible precisely because the runtime engine decouples the calling of methods from their compilation. The Smalltalk programmer can compile messages at will, and not worry whether methods exist to respond to them until the instant before they're called.

By contrast, adding or removing a C++ method requires recompilation of potentially many v-tables to preserve their parallel structure. And although we know that polymorphic client code does not need to be rewritten, it must still be *recompiled* to account for new offsets to the pointers in the tables. This recompilation overhead discourages exploratory programming. On the other hand, C++ cooperates readily with foreign languages, while Smalltalk's runtime engine gets in the way of calling into or out of the Smalltalk image.

## 16.3 Memory management: a brief history of garbage collection

A Smalltalk programmer doesn't manage storage for her objects. In particular, when she's done with an object, she doesn't worry about reclaiming the memory occupied by the object. Instead, a component of the virtual machine known as the *garbage collector* monitors memory and ascertains when it can safely reclaim the memory occupied by an object.

Consider this question: how many point objects are present in your Smalltalk system? The answer is easy to determine. I can count them by *displaying*:

```
Point allInstances size
```

The answer on my system at this moment is 13. If I allocate a new point:

```
X := Point new
```

and count again, I get one more, 14. If I now *execute*:

```
X := 'Casablanca'
```

the global variable X refers to a string instead of the point. The point has been orphaned—although it was once accessible through the variable X, it is now completely inaccessible—and is therefore eligible for garbage collection. If I count again, Smalltalk reports 13, the original number of points. The garbage collector has reclaimed the memory occupied by the newest point. Here is the progression of events:
<figure><img src="image_107.png" /></figure>

After
assignment

<figure><img src="image_108.png" /></figure>

After
reassignment

<figure><img src="image_109.png" /></figure>

After
collection

Garbage collection in Smalltalk contrasts sharply with memory management in C++ and many other compiled languages that permit a program to acquire chunks of memory while it executes. Because C++ has no garbage collector, the programmer must carefully and explicitly reclaim an object's storage at the appropriate moment. The dangers of entrusting this responsibility to the programmer are well known: freeing an object's memory too soon invites another object into the space, corrupting the original object's data. And failing to free memory soon enough exposes the program to running out of room for additional memory allocations. These are among programming's most nightmarish bugs; they often manifest themselves as catastrophic crashes that occur well after the event, considerably complicating debugging.

On the other hand, a garbage collector is a program that runs continually, consumes CPU cycles, and, being beyond the programmer's control, can become especially active at inopportune moments. Critics observe that an airplane's control system or a nuclear power plant's monitoring system can ill-afford to pause while a garbage collector decides to shift into high gear. The traditional debate goes like this:

* Pro: Only a garbage collector can safeguard against application crashes induced by subtle and inevitable errors in memory design.

* Con: Only a programmer can fine-tune memory management for high-performance applications. In particular, a garbage collector's sporadic intensification makes it unacceptable for real-time software.

Next, by examining how garbage collectors work, we will gain insight into the lives and deaths of objects. This is a useful study regardless of your position in the (endless) debate on the merits of garbage collection.

Most early garbage collectors, prior to the mid-1980s, were variants of either *mark-and-sweep* or *reference-counting* collectors. A mark-and-sweep collector makes two passes through memory. The first pass begins at one or more *anchor* objects that the virtual machine knows it needs (like the *activation stack* in Smalltalk, which contains all executing methods and the objects they refer to).
<figure><img src="image_110.png" /><figcaption>Before mark
pass</figcaption></figure>

<figure><img src="image_111.png" /><figcaption>After mark
pass</figcaption></figure>

<figure><img src="image_112.png" /><figcaption>After sweep
pass</figcaption></figure>

The anchor object is "marked"—let's say a bit is turned on—and then all objects the anchor refers to are also marked, and then all objects these objects refer to are marked, and so on recursively until no more objects are reachable. At the end of this mark pass, objects that remain unmarked must be inaccessible and are therefore garbage objects, eligible for reclamation. A second pass sweeps through all the objects, reclaiming space from unmarked objects and turning off the mark bit on all others, preparing them for further collections.

A major drawback of this scheme is its burstiness—the collector may not often go into action, but when it does, the rest of the system freezes while it makes these two exhaustive passes through memory. The user experiences a long pause during which nothing seems to happen.

Reference counting isn't bursty; a reference-counting collector does some bookkeeping every time a pointer is set or reset. The collector maintains a count of the number of references to each object. If a count ever drops to 0, that object must be inaccessible, and the collector immediately reclaims its storage:

<figure><img src="image_113.png" /><figcaption>Before</figcaption></figure>

<figure><img src="image_114.png" /><figcaption>Adjust count
immediately</figcaption></figure>

<figure><img src="image_115.png" /><figcaption>Reclaim
immediately</figcaption></figure>

Reference counters eliminate the distracting pauses of mark-and-sweep collectors. On the other hand, reference counters never rest, so the overhead of maintaining the counts degrades performance continuously. Reference counters also overlook *dead cycles*. For instance, a pair of objects may refer to each other but still be isolated from the rest of the system; their counts will each be 1, hence they are not reclaimable, even
though they are genuine garbage. Reference counting by itself is therefore insufficient to collect all garbage correctly. Nevertheless, the earliest Smalltalks used reference counting because it is straightforward to implement and it eliminates pauses.

Another famous older collector, sometimes called a *Baker collector* [Baker 1978], addresses shortcomings of both preceding schemes. It suffers neither reference counting's susceptibility to dead cycles, nor mark-and-sweep's two full passes through memory. A Baker collector partitions memory into two halves, known as *semi-spaces*. All new objects are allocated in one of the semi-spaces, designated the *active one*. The collector occasionally flips spaces, making the other one active. But before opening up the new active space to additional object allocations, it makes one pass through the old semi-space, starting from an anchor, just like a mark-and-sweep collector. And just as in a mark pass, it recursively reaches only all the live objects. Instead of marking them, however, it immediately evacuates each one by moving it into the new semi-space. In the object's original place, it leaves a *tombstone* with a forwarding address to the new location, just in case other objects come looking for it later during the pass. At the end of this single pass, all live objects have been evacuated into the new active space; the detritus in the old semi-space is garbage and requires no further processing.

<figure><img src="image_116.png" /></figure>

In due course another flip occurs, in the opposite direction. Notice that as a result, each flip enjoys an entirely clean semi-space into which objects are moved and allocated. I'll say more about the benefit of this cleanliness in a few moments.

The Baker collector has a cunning wrinkle: with a little care, the flip can proceed *incrementally*. That is, new object allocations can begin before the flip finishes; the collector can make these allocations in the new active space while it continues to evacuate live objects from the old space. The one danger is that one of the newly allocated objects may point back to a (not yet evacuated) object in the old active space; such a pointer will be incorrect at the end of the flip. To safeguard against this condition, the collector must move the unevacuated object immediately, ahead of schedule. Once this precaution, known as *scavenging*, has been taken, the Baker collector is truly incremental and, like the reference counter, overcomes the burstiness of a mark-and-sweep collector.

One undesirable property shared with mark-and-sweep collectors remains—Baker collectors process live objects over and over again. The profusion of live objects in Smalltalk—from 15,000 in a small Smalltalk system to more than 278,000 in the
image I'm using at this moment—makes this a considerable burden. If only we had a way to overlook objects that are particularly durable, thereby sparing us the overhead of repetitious reprocessing. This observation brings us to *generation scavenging*, which late in the 1980s became the de facto standard for Smalltalk garbage collection.

Generation scavengers depend on the empirical observation that most objects per- ish quickly. New objects—points, arrays, sets, rectangles, blocks...—are created like mad in running Smalltalk systems, used briefly, then orphaned. The garbage collector must process these objects, but we would like it to ignore as much as possible the other tens or hundreds of thousands of longer-lived objects.

A scavenger begins just like the Baker collector, but every time it flips an object, it also increments the object's *generation count*. An object that survives *n* flips will be *n* generations old. The scavenger deems objects that survive to some threshold age, let us say three generations, venerable enough to move to a privileged area, called the *tenured area*.

<figure><img src="image_117.png" /></figure>

Once tenured, objects are no longer subject to repetitive garbage processing. Thus, short-lived objects are efficiently collected by Baker flips, and long-lived objects are promoted eventually to the tenured area, where they are left quietly alone. The opportunities for varying the basic scavenger design are evidently multitudinous—how many generations to allow before tenuring (63 in the original VAX implementation), how to process a tenured object if it perishes, whether and when to age tenured objects into successively more securely tenured areas.... A good generation scavenger consumes as little as 3 percent of CPU time, compared to 9 to 20 percent for the older techniques. For a sampling of scavenging schemes, see [Lieberman and Hewitt 1983; Krasner 1984; Samples et al. 1986; Ungar and Jackson 1988]. In particular, [Krasner 1984] recaps the history of the early VAX Smalltalk-80 implementations through more and more sophisticated garbage collectors—first mark-and-sweep, then Baker, and finally a generation scavenger.

## 16.4 The irony of garbage collection

The remarkable irony about garbage collectors is that their reputation for consuming processing cycles is half wrong. Some of them also save cycles. Curiously, these savings have nothing to do with cleaning up objects; they occur at the other end of an object's life, when its memory is first allocated. The savings have to do with the clean spaces I mentioned earlier.
A side-effect of schemes like the Baker collector and the generation scavenger is that object allocations occur in one large, contiguous chunk of free memory. Memory has no holes, no gaps that must be computed and accounted for. This absence of "fragmentation" considerably simplifies allocation; finding space for a new object is a mere matter of returning the location of the beginning of free memory and then advancing this beginning by the size of the object. New objects simply go right after the last object in memory.

By contrast, the heaps found in C, or Pascal, or C++ are full of holes and gaps. Memory allocation schemes must rely on one or more chains of holes. Each object allocation entails a search through these chains for space of adequate size, followed by adjusting the chain to reflect the space relinquished to the new object. Searching and managing these chains takes time, which is why fragmentation is the enemy of efficient object allocation, and conversely why clean spaces enable fast object allocation.

Thus, garbage collection, which purports to worry about the end of an object's life, can in fact expedite its birth. The effect is measurable: adding a garbage collection scheme for a C++ application's objects can sometimes *improve* the performance of the application. Regardless of the performance implications, the main benefit of garbage collectors stands: by automating storage reclamation they reduce the incidence of memory design errors.

## 16.5 Commentary: why not garbage collect C++?

If garbage collection is so beneficial, why can't it be retrofitted onto any language? Garbage collection is possible in Smalltalk because all objects have a uniform structure known to the virtual machine. Everything is an object, and every object's memory layout begins with a standard three-word header, consisting of a pointer to the object's class, some flags, and the object's size. (Each word is four bytes.) After these three words come the object's instance variables, one word per instance variable.

Knowing this regularity, the memory manager (i.e., the garbage collector) can figure out where an object begins and ends, and most critically, where the objects it points to are. Any garbage-collection scheme needs this information. Unfortunately, in a language like C++, the contents of an object are arbitrary. Within the memory of an object is a jumble of information—data, pointers, even other objects directly embedded inside. A memory manager cannot know where all the pointers are, and so it cannot find the objects pointed to. That kind of information is in the semantics of the program, where it is inaccessible to a hypothetical virtual machine. Hence, you will find that all object-oriented languages with garbage collectors—Smalltalk, Eiffel,
CLOS, Java...—adopt a uniform object structure. C++ is as flexible as can be, hence lacks this uniformity; it therefore precludes garbage collection of arbitrary objects.

For the definitive discussion on the desirability of and prospects for garbage collection in C++, see [Stroustrup 1994].

## 16.6 Smalltalk deviates from uniformity

Even Smalltalk, insistent as it is on uniformity, has its limits. Methods, for instance, are written in Smalltalk and call other Smalltalk methods. Carried on indefinitely, this recursion would be hopelessly circular. Some Smalltalk methods must be expressed in something other than Smalltalk. These methods are called *primitives*. They are typically written in a language like C, compiled, and packaged into a "dynamic link library" (on Windows or OS/2), from which they may be called by a Smalltalk method. An example is integer multiplication. The method `SmallInteger>>*` reads:

```
* aNumber
  "Answer a ... "
  <primitive: VMprSmallIntegerMultiply>
  "... more code ..."
```

The very un-Smalltalk-like expression `<primitive: ...>` is the call to a special function outside of Smalltalk. (The code following the primitive executes only if the primitive call fails.)

Primitives need not be limited to low-level methods like multiplication. Because a primitive is essentially a way to call a foreign language from Smalltalk, it can also be used to access functions that Smalltalk doesn't provide, or to replace a slow Smalltalk method with a faster version coded in another language. Primitives are the means by which Smalltalk issues calls to outside services like database managers or communication programs.

Another area in which Smalltalk is not uniform is its storage model. Most objects conform to the standard structure I discussed in the preceding section; that is, three header words followed by the object's instance variables. But objects such as small integers—those which fit with room to spare in a 32-bit word (or 16 bits, in some implementations)—are created and used so commonly in Smalltalk that the overhead of the standard structure would be grossly inefficient. Smalltalk therefore dispenses with the header for these objects and stores the whole object in one word. This special treatment for small integers and other small objects saves both time and space. But it introduces an irregularity into the virtual machine.
Smalltalk goes further with its special treatment of small integers. Not only are they stored in a different format, they are also stored "in-line." Here's what I mean: ordinarily you would expect assignments like `X := someWhale` and `Y := 149` to establish pointers to a whale and integer object, respectively. Indeed, the word in memory specified by `X` does contain a pointer to a whale object. But the word specified by `Y` contains the small integer 149 itself, not a pointer to 149. Thus the layout of memory inside the image might look like this:

<figure><img src="image_118.png" /></figure>

Accessing small integers directly, rather than through a pointer, is much more efficient for the virtual machine. But how does the virtual machine know whether a word is a pointer to an object (X) or the object itself (Y)? It recognizes the difference by using a flag bit, such as the first bit in the word. If the bit is turned on, the word represents a small integer. Otherwise it represents a pointer to a conventional object. (Actually, several other special small objects are distinguished by specific bit patterns too: characters, the true and false objects, and the nil object. They are known collectively as immediate objects.)

You will never observe any of these storage conventions at the Smalltalk level. These are strictly private conventions for use by the virtual machine. Smalltalk continues to deceive the developer into believing that, "Everything is an object, and all objects are treated uniformly."

While we're on the subject of economy, realize that even packing individual character objects into a word apiece squanders a lot of space, namely three bytes of every four. This waste is particularly excessive when, as is the case more often than not, they occur together, as in a *String* object. For strings too, the Smalltalk virtual machine deviates from uniformity for the sake of efficiency. The characters in a string occur in successive bytes, right inside the string object, illustrated in these alternative memory layouts for the string 'juice':
<figure><img src="image_119.png" /></figure>

Smalltalk offers other specialized formats for storing the instances of a class. Most classes simply use the standard structure of three header words followed by a word per instance variable. But you can specify the other formats to use at the time you define your classes—you will see how in the coming exercises.

## 16.7 Exercises

### Inspecting classes

* You know how to find the superclass of a class using Smalltalk's browsers. Try it in another way by using `inspector(s)` to find the superclass of `Date`.

* Use inspectors to find the bytecodes—numbers like `132`, `36`...—for the method `dayOfYear` in the class `Date`. Begin by inspecting the class `Date`; in IBM Smalltalk, inspect down through the instance variable `methodsArray` rather than `method-Dictionary`.

### Object memory layouts

* Although the memory layout of objects is strictly the business of the virtual machine, you can see intimations within Smalltalk that the instances of some classes are treated differently than others. For example, the classes like `String` that
store their data in consecutive byte-sized objects answer true to the message `isBytes`. To see how many such classes there are, inspect this expression:

`Object allSubclasses select: [:sc| sc isBytes].`

* How does Smalltalk know whether to lay out objects of a class in the usual way, or in the compressed form that strings use? To answer this question, browse the definition of an ordinary class like `Rectangle`, and compare it to the definition of `String`. Confirm that ordinary classes are created by the old standby:

`subclass:instanceVariableNames:classVariableNames:poolDictionaries:`

What method does class `String` employ? This is the method that informs the virtual machine that it should use the compressed-memory layout for strings.

* How many other conventions does Smalltalk have for laying out objects? Hint: Locate the class that implements the class definition messages above and look for similar methods.

## Counting instances

* To estimate the number of classes within your Smalltalk image, display:

`^Object allSubclasses size.`

For reasons that you will understand when we discuss metaclasses in Chapter 20, this estimate is about twice as high as it should be.

* You can count the number of objects in your Smalltalk image by displaying:

```
|count|
count := 0.
Object allSubclasses do: [:c| count := count + c1 allInstances size].
^count
```

But try this experiment overnight—it may take hours. That's because the `all-Instances` method invokes a full-blown garbage collection, and we are invoking it once for every class.<fnref n="1" />

<footnote n="1">¹ In IBM Smalltalk you can get a quicker but less precise count by using `basicAllInstances`, which does not invoke garbage collection. You can sharpen this count by clearing the garbage once in the beginning with the message `System globalGarbageCollect`. Nevertheless, be prepared to wait a while.</footnote>
## Non-uniformities in Smalltalk's compiler

Not all messages are equal. That is, Smalltalk's compiler recognizes a few special messages and generates optimized code for them. You can rewrite and recompile those methods in any way you like, but your code, whatever you write, will be ignored.

* To demonstrate this curiosity, recompile the `ifTrue:` method in class `True` after inserting `self halt` into its body. Then display:

```
7 = 7
ifTrue: [ 'Breezing through the halt' ].
```

The same short circuit applies to all the other common boolean messages, like `ifTrue:ifFalse:`, `ifFalse:`, etc. Another noteworthy message that the compiler intercepts in this fashion is `==`.

**Technical aside:** The only way to circumvent the compiler's optimization and force your rewritten method to execute is to invoke it indirectly. The usual technique is to use variants of the method `perform:`, as in:

```
7 = 7 perform: #ifTrue: with: [ 'Hit my halt' ]
```

## 16.8 Summary

Every implementation choice in an object-oriented language is a tradeoff. If method dispatch is fast, compilation will be slow. A garbage collector will reduce the number and severity of bugs, but degrade performance. A compiler optimization speeds up a corner of the language, but at a loss of consistency in the language. An image can be portable, but it won't enjoy the platform's native widgets. Virtual machines make interactive debugging a snap, but complicate life with foreign languages.

This interplay between a language's definition and its underpinnings shapes the whole texture of the programming system—its responsiveness, its reflectiveness, the degree of its coupling to other languages and systems, even the design techniques that are most suitable in it. Smalltalk—the product of one combination of all the choices—is a respectable point in the space of object-oriented languages.

We now shift from the guts of object-oriented languages to a conceptual predica-
ment that awaits practicing object-oriented designers.
## Two kinds of inheritance

Next in our series of beyond-the-basics topics is the distinction between a type and a class. Until now we've blurred this distinction: I've encouraged you to think that inheritance is simply synonymous with the AKO (A-Kind-Of) concept. Seasoned designers, however, cringe at this oversimplification.

### 17.1 Beauty and the beast

Consider two classes, **Rectangle** and **Square**, in any object-oriented environment. Don't worry about Smalltalk; the first four sections in this chapter are independent of the object-oriented language. Here are rectangle and square instances:

<figure><img src="image_120.png" /><figcaption>aRectangle</figcaption></figure>

<figure><img src="image_121.png" /><figcaption>aSquare</figcaption></figure>

Each has a method for calculating its area and instance variables to identify its position (let's say the upper-left corner) and the length of its side(s). We won't worry about rotation—all our squares and rectangles will have vertical and horizontal sides only.

Now, a design problem: should **Rectangle** be a superclass of **Square**? Or vice versa? Two perfectly defensible opinions are:
1. Squares are special kinds of rectangles, namely those which have sides of equal length. Every schoolchild knows this fact. Therefore, **Square** should be a subclass of **Rectangle**.

2. We expect a subclass to inherit everything from its superclass and, generally, to add further traits. Butterflies have all insect traits, plus more. The picture above clearly shows that a rectangle has the traits of a square, plus one additional instance variable. Therefore, **Rectangle** should be a subclass of **Square**.

Before you get excited about one point of view or the other, let me tell you once and for all that there is nothing wrong with either argument. The dispute is unavoidable: there are two reasons for subclassing, and they aren't always compatible. (And if one finds neither reason compelling, one can always design *neither* class to be a subclass of the other; this is a valid third alternative.)

Imagine two object-oriented programmers, one a *consumer* of a class hierarchy and the other the hierarchy's *producer*. The consumer wants to reach over and use ("buy") the classes in the hierarchy with minimal confusion. He doesn't want surprises; he expects the hierarchy to be an intuitive AKO hierarchy, and he definitely doesn't want to examine any underlying code or instance variables. Like the schoolchild, he expects **Square** to be a subclass of **Rectangle**. The consumer values external *consistency*.

The producer or developer of the hierarchy, on the other hand, cares how well the *insides* of objects work. She has two reasons for subclassing **Rectangle** from **Square**. First, her job is simpler because she automatically inherits the instance variables *position* and *side*, and just adds an instance variable for *side2*. (Of course, she must override the *area* method to calculate the product of *side* and *side2*.) Second, she worries that if she subclasses in the other way, every square inherits an extra instance variable (*side2*) it doesn't need; if a graphics application uses thousands of squares, it will waste a lot of memory. This developer values *practicality*.

The dilemma, then, is this conflict between consistency and practicality. You can't inherit at the same time for the sake of an attractive appearance on the outside and for the sake of code reuse and machine constraints on the inside. A class hierarchy can't at once satisfy its consumer and its producer.

We need to sharpen our vocabulary. The term for the first kind of hierarchy, the one that is externally attractive ("beauty"), is a *type* hierarchy. When that's the focus, we use the words *type* and *subtype*. AKO, which implies consistency, is really subtyping.

The second hierarchy, the one favoring internals ("the beast"), goes by the familiar words *class* and *subclass*, and frequently the expression *implementation inheritance*. Of course, in practice you often see the word "inheritance" by itself. Generally, when experts draw fine lines and say just "inheritance" they mean implementation inheritance. To minimize the risk of confusion in this chapter, I will avoid using "inheritance"
by itself unless the context is unambiguous—it will either be “subtype inheritance” or “subclass (or implementation) inheritance,” or simply “subtyping” or “subclassing.”

The object community first recognized the troubling presence of these two distinct forms of inheritance in 1986. (See [Snyder 1986; Lalonde et al. 1986].) Efforts to wrestle with the trouble produced several evocative synonyms:

<table><thead><tr><th>Subtype Inheritance (Beauty)</th><th>Subclass Inheritance (Beast)</th></tr></thead><tbody><tr><td>Subtyping</td><td>Subclassing</td></tr><tr><td>Specification inheritance</td><td>Implementation inheritance</td></tr><tr><td>Visible inheritance</td><td>Invisible inheritance</td></tr><tr><td>Essential inheritance</td><td>Incidental inheritance</td></tr></tbody></table>

For details, see [Snyder 1986; Sakkinen 1989; Wegner and Zdonik 1988]. By whatever names, it became clear that the subtype/subclass distinction was an inescapable fact of object-oriented life.

## 17.2 Why types matter: polymorphism

The type (beauty) of an object is the means by which a consumer programmer recognizes an object's applicability to some problem. For S to be a subtype of T (imagine **Butterfly** and **Insect**, or **Square** and **Rectangle**), the external description of S ought to be consistent with that of T. And if so, you would expect to be able to use an instance of S anywhere in a program where the program expects something of type T. This property is called *substitutability*: an instance of a subtype may be substituted wherever something of the supertype is expected and the program will still work. Thus anywhere a rectangle works in an application, a square also works; the application musn't fail because someone has substituted a square for a rectangle. This is what we mean by saying that **Square** is a subtype of **Rectangle**.

The converse, however, is false. If an application depends on a square, say to form the faces on the dice for a game of craps, an arbitrary rectangle just won't do. Thus **Rectangle** is not a subtype of **Square**.

This freedom to substitute instances of a subtype sounds suspiciously like polymorphism, and indeed that's just what it is. In polymorphism, the program is unaware of the actual type of the object lurking under a variable—any subtype will do. The subtype relationship specifies what is substitutable, hence the permissible range of polymorphic objects. To put it bluntly, substitutability and polymorphism amount to the same idea.
Another way to think about substitutability is to think about variables s and t of types S and T, respectively. Freedom to substitute an S instance wherever a T instance is expected justifies assignments of the form $t := s$. This is the same rule we saw for C++ (page 168). An insect variable may refer to a butterfly, but not conversely.

All the following terms, then, are allied: *AKO*, *subtype*, *substitutable*, *consistent*, and *polymorphic*. All represent beauty, which is different from the notion of a *subclass*. From now on we need to respect this distinction.

## 17.3 Commentary: an aside on subsets

A type generates a set. (Or at least something very much like a set. Mathematicians and logicians would quibble about using the word "set" here. I alluded to this fussiness on page 13.) For example, the type *Butterfly* generates the set consisting of all the butterfly objects that might ever be created.

Following this reasoning further, if S is a subtype of T, then the set generated by S is a subset of the set generated by T. That's because we have agreed that subtyping means S is consistent (AKO) with T, which implies that S's objects satisfy whatever T's objects satisfy. In other words, S's objects constitute a subset of T's objects. In everyday language, butterflies constitute a subset of insects and squares constitute a subset of rectangles.

Although subtypes generate subsets in a natural way, it would be reckless to assert the converse, that by taking any arbitrary subset of the supertype's objects, with methods defined to be the same as the supertype's methods, we'd get a subtype. That's because methods that make sense on the superset might not make sense for the subset. For example, suppose rectangles have a "squish" method that doubles their length and halves their width. Squares, although forming a legitimate subset of the set of rectangles, can't be squished. Squares then wouldn't understand the same messages that rectangles do, and so in the presence of squishing, they wouldn't constitute a subtype.

**Conclusion:** Subtypes naturally generate subsets, but subsets do not necessarily define natural subtypes.

## 17.4 Commentary: what does "consistency" mean?

Intuitively, we understand subtyping to mean preserving the hierarchy's external consistency. But so far we do not have a precise definition of "consistency." For instance, birds fly, but penguins don't. Would we want to say that penguins form a subtype of birds or not? Are penguins consistent *enough* with birds to warrant being a subtype?
What conditions should their fly method abide by to be consistent with the fly method for birds?

More rigor is evidently desirable. We'd like an objective test for consistency. Unfortunately, no one test exists. The candidates range from the weakest condition, where it doesn't take much to be consistent, to the strongest, most rigid condition, where it's extremely difficult to be consistent.

Here are four candidates, covering the spectrum from weakest to most rigid. In order of increasing strength, we'll call them *anarchy*, *conformance*, *behavioral consistency*, and *rigidity*.

*   **Anarchy.** S has at least all the message selectors that T has, and possibly more, but there are no limits on what the method bodies themselves do. For example, if Bird has a fly method, then the subtype Penguin must too. But Penguin>>fly may answer No! while Bird>>fly answers Yes! Yet more flagrant, Penguin>>fly might answer a special error object or generate a walkback, informing you that you should not have sent the message in the first place. The effect would be to cancel the Bird>>fly. The possibilities for Penguin>>fly being unlimited, anarchy barely deserves to be called subtyping. Yet it is what Smalltalk allows. Smalltalk imposes no restrictions on what a subtype method does. This is such a weak form of consistency that one could say in good conscience that it isn't in the spirit of subtyping at all. And it is often said that Smalltalk programmers don't really subtype; they subclass.

*   **Conformance.** We now depart from Smalltalk; conformance can be checked only by a language whose variables have types and as we know, Smalltalk's do not. Neverthe- less, as an object designer, you can still think about conformance, and knowing about it can improve your designs.

Conformance has to do with the consistency of the types of arguments and return values of methods. I will discuss the most widely accepted definition. First let's adopt the convention that the word "subtype" includes the type itself. A type then is always a subtype of itself, and also a supertype of itself.

S will conform to T if its methods follow certain rules. The gist of these rules is to force each method to "deliver more" and "require less" than the corresponding method in T. By delivering more and requiring less, S's instances will be more accommodating. Therefore S's instances can be substituted wherever T's instances are called for.

That's the outline; now the specifics. We need to think about the return types and argument types of a method. First, the return type.

Consider methods for laying eggs, Duck>>lay and Bird>>lay. Bird>>lay returns an instance of Egg, and Duck>>lay returns an instance of DuckEgg. Thus Duck's method returns a more specific type of object than Bird's method does—ducks
deliver more than birds do when they lay. We say that the return type of `Duck>>lay` conforms to the return type of `Bird>>lay`.

The official wording is: for the return types of a method `m` to conform, the type of object returned by `S>>m` must be a subtype of the type returned by `T>>m`. (Remember that the types of the returned objects may be equal, too.) The right-hand side of this schematic illustrates the possible objects returned by `T>>m` (`Bird>>lay`) and `S>>m` (`Duck>>lay`). (Ignore the left-hand side for now.)

<figure><img src="image_122.png" /></figure>

Notice that fewer objects may be returned by `S>>m` than `T>>m`—only duck eggs, not all eggs. That is the key. The objects returned by `S>>m` are more specific; they represent a subtype or subset of the objects returned by `T>>m`.

That's the rule for conformance of return types—it's drearily straightforward. The rule for argument types, however, has a twist. We will need a little extra notation: `S>>m(P)` means that the method `m` accepts an argument of type `P`. We are going to define what it means for the types `P` and `Q` of the arguments of the method `S>>m(P)` and method `T>>m(Q)` to conform.

Consider `Piano>>play(Pianist)`; in other words, the play method for pianos requires an argument, namely a pianist. Think about the `ConcertGrand` subtype of `Piano`. Who can play a concert grand? In other words, what condition should we impose on the argument type of `ConcertGrand>>play()`?

It is tempting to argue that the argument type ought to be the `Virtuoso` subtype of `Pianist`. But this impulse turns out to be dead wrong, at least for this interpretation of conformance. That's because we want our rules to guarantee substitutability, and if we demand that only a virtuoso can play a concert grand, then the concert grand will not be substitutable for the piano! (For example, imagine the piano in my living room being played by a pianist. We want to roll in a concert grand to replace it and for the living room to continue to operate normally. Well, it won't if we
suddenly require a virtuoso instead of a pianist. The only way for the substitution to work is if the concert grand may also be played by a pianist, or even possibly a more general type of individual, like Person.)

Paradoxically, to guarantee substitutability, I have to make my Concert-Grand>>play(__) method accept a supertype of Pianist as an argument! This rule makes the software consistent, although it may not do much for musicality. (A design technique known as multi-methods preserves the musicality of this problem. The idea is to treat Piano and Pianist as peer classes and to imagine a "method" that operates on both objects at once. This outlook differs from our customary object-centric perspective, where we always have a preferred object. For a discussion of multi-methods, see the commentary on page 170.)

Thus conformance of argument types works in the opposite direction from conformance of return types. The official definition must be: for the argument types of a method m to conform, the type of an argument of S>>m must be a supertype of the respective argument of T>>m. (Again, the types may be equal, too.) Looking back at the left half of the schematic above, you can see that S>>m (Concert-Grand>>play) accommodates more possible arguments than T>>m (Piano>>play). The arguments that S>>m accepts represent a supertype or superset of those that T>>m does.

Putting everything together into a definition of subtype based on conformance, we can say that for S to be a subtype of T, S must have all T's methods and possibly more, and for any method m in both S and T, S>>m's return and argument types must conform to T>>m's. (Notice that this definition is recursive: the subtype relationship between S and T is cast in terms of the subtype relationships of arguments and returns. Recursions need a condition to get them started or stopped, and we started this one by declaring that any type is a subtype of itself.)

Here's another way to express this definition, using some jargon that has caught on in the C++ community but which originated in the mathematical discipline known as category theory. Return types follow a covariant rule—they vary in the "same" direction as S and T. That is, if S is a subtype of T, then the return of S>>m must also be a subtype of the return of T>>m. Argument types follow a contravariant rule—they vary in the "contrary" direction from S and T. That is, if S is a subtype of T, then an argument of S>>m must be a supertype of the respective argument of T>>m. Briefly then, S is a subtype of T if S has all T's methods and possibly more, and any methods in common follow covariance in their returns and contravariance in their arguments.

This subtyping rule—conformance—reflects a theoretical ideal whose essential appeal is substitutability. Each language defines its subtyping rule in its own way,
usually not in accordance with the ideal. In Smalltalk, conformance is irrelevant because of the typelessness of Smalltalk's variables. Even among languages whose compilers check for the types of arguments and returns, few (see the upcoming table) adopt the ideal.

For example, Eiffel's rule for consistency of argument types is the *opposite* of what we've discussed—covariance instead of contravariance. Eiffel's rule has been the subject of vigorous debate (see [Cook 1989]). Its rationale is that covariance of argument types is in practice more useful than contravariance. Concert-Grand>>play(Virtuoso) should conform to Piano>>play(Pianist) because practicality (musicality) should prevail over any lofty desire for consistency (substitutability). ConcertGrand>>play(Person) may be theoretically sound, goes the Eiffel argument, but it has no practical value.

*   **Behavioral consistency.** By behavior, I mean the semantics of methods; that is, what they do rather than merely their names or selectors or signatures. The spirit is the same as for conformance: for S to be a subtype of T, S>>m should require less (behaviorally) and deliver more (behaviorally) than T>>m.

How can we specify a method's behavior? The customary technique is to use *pre-conditions* and *postconditions*. These mean just what they say: preconditions consist of what the method expects prior to its execution (i.e., what it requires) and post-conditions consist of what it guarantees when it finishes (i.e., what it delivers). Therefore, requiring less and delivering more simply mean *weakening* the preconditions and *strengthening* the postconditions.

Thinking about preconditions and postconditions for your methods is good discipline, even though all you can do about it in Smalltalk is record the conditions informally in comments. Computer scientists don't have a practical way to formally specify and validate preconditions and postconditions anyway. So there is nothing shameful about documenting methods with informal preconditions and postconditions in their comments. Only Eiffel among the commercial object-oriented languages has even rudimentary support for checking this kind of consistency.

*   **Rigidity.** The strongest possible form of consistency would be to categorically forbid alternate implementations of a method. For an object-oriented developer, this is an academic, useless notion. S could only add brand-new methods to T's methods. Penguins could add any number of methods to bird methods, but penguins could not have their own fly method. Instead they could only reuse the fly method from birds. Penguins must then fly like any other bird, an unsatisfactory condition. No object-oriented language is this rigid. Prohibiting alternate implementations entirely would produce an unacceptable object-oriented language.
Now let's relate these theoretical ideas to the rules for consistency in actual object-oriented languages. The table below describes these rules for several languages. Think of them as the rules that determine when polymorphism or substitution works. The first column indicates whether substitutability requires an explicit implementation inheritance relationship between S and T; that is, a declaration of S as a subclass of T. The remaining columns describe how far each method S>>m may deviate from the method T>>m.

<table><thead><tr><th rowspan="3"></th><th rowspan="3">Must S subclass from T?</th><th colspan="3">When S is substitutable for T (polymorphism)</th></tr><tr><th colspan="3">For S>>m to be consistent with T>>m</th></tr><tr><th>Return types</th><th>Argument Types</th><th>Behavioral Conditions</th></tr></thead><tbody><tr><td>C++</td><td>Yes</td><td>Covariant</td><td>Must agree</td><td>n/a</td></tr><tr><td>Eiffel</td><td>Yes</td><td>Covariant</td><td>Covariant</td><td>May weaken preconditions or strengthen postconditions</td></tr><tr><td>Emerald</td><td>No</td><td>Covariant</td><td>Contravariant</td><td>n/a</td></tr><tr><td>Java</td><td>No</td><td>Covariant</td><td>Must agree</td><td>n/a</td></tr><tr><td>Modula-3</td><td>Yes</td><td>Must agree</td><td>Must agree</td><td>May raise fewer exceptions</td></tr><tr><td>POOL-I</td><td>No</td><td>Covariant</td><td>Contravariant</td><td>May have more "properties"</td></tr><tr><td>Smalltalk</td><td>No</td><td>No restriction</td><td>No restriction</td><td>n/a</td></tr><tr><td>Theoretical ideal</td><td>No</td><td>Covariant</td><td>Contravariant</td><td>May weaken preconditions or strengthen postconditions</td></tr></tbody></table>

Polymorphism in C++ was originally conservative: any change to the declared types of arguments and returns waived polymorphism. But the ANSI C++ committee took a small step toward conformance in 1993 by allowing covariance for return types, as shown in the table.

Note that only the research languages Emerald and POOL-I support ideal conformance—covariance in return types and contravariance in argument types. For further information on the type systems of the languages in the table, see: [Stroustrup 1991; Meyer 1992; Black et al. 1986; Sun 1995; Cardelli et al. 1992; America 1991; Goldberg and Robson 1983].
## 17.5 Consistency and Smalltalk

What has this discussion of topics like conformance to do with Smalltalk, where variables don't have types in the first place? Well, just because the designer can't express these ideas in the Smalltalk language doesn't mean she is incapable of thinking about them. It would be a peculiar designer indeed who was oblivious to the concept of consistency. And that is the rub of this chapter: to warn you that as a Smalltalk developer you will have to reconcile your idealistic thoughts about consistency with the absence of means to represent these thoughts in your software. You have just one inheritance mechanism, and the path of least resistance is to use it for subclassing.

Beginners are mostly motivated by AKO (subtyping), but gradually, as they become familiar with classes and their workings, they begin to inherit for the sake of reusing the code they find—they subclass. In the end, expert Smalltalk programmers use inheritance frequently for subclassing. The reason is simple. In Smalltalk, more than other object-oriented languages, when you inherit, you inherit *everything*—all the instance variables and all the methods. You get access to all the insides, whether you want them or not. It's a producer's sandbox.<fnref n="1" />

The Smalltalk developer, hobbled by having to inherit all the insides, has no way to define a type hierarchy. The limitation is grim, but not as grim as it sounds. Often, class and type hierarchies are the same or nearly so, which explains why many Smalltalk developers survive without knowing the difference. Often, but not always. What would we see if we masked Smalltalk's class hierarchy and looked instead for subtype relationships?

William Cook did this experiment for the collection classes in Smalltalk-80 and found... an entirely different hierarchy! [Cook 1992] In the next exercise, you'll replicate his experiment.

<footnote n="1">¹ Technical aside: By contrast, C++ offers more control over inheritance. *Private members and private inheritance* in C++ limit what subclasses can access and what consumers of the subclass can access. These features distinguish what a class inherits for the sake of its own implementation from what it inherits for the sake of its appearance to the consumer—a step toward separating subtyping from subclassing. Java goes further. It supports two distinct notions—conventional classes plus *interfaces*. An interface specifies a set of method names. The programmer can develop separate class and interface hierarchies, associating specific classes with specific interfaces at will. And as you may have guessed, polymorphism (substitutability) in Java depends on an object's interface, not its class.</footnote>
## 17.6 Exercise: Smalltalk's container "types"

Consider these container classes: `Array`, `Bag`, `Collection`, `Dictionary`, `Set`, and `String`. (A bag is like a set, except that an element can occur more than once in a bag; you cannot add an element twice to a set.) Our goal is to arrange them into a reasonable type (AKO) hierarchy. To do so, we have to examine public selectors that are appropriate for consumers of these classes. Here is a representative list—`size`, `at`, `at:put`, `includes`, `<`, `indexOf`, `remove`, `removeKey`, `add:withOccurrences`. This is a somewhat contrived subset of methods—a complete assessment would entail all public methods—but we want to keep the exercise manageable.

We also have to settle on some definition for consistency. Let's use a simple one: S is a subtype of T if S has all the selectors of T, and they all work. This is a little more fastidious than the anarchic subtyping rule (page 202), because we are saying that we don't want to count methods that issue an error. A deliberate error in a method tells us that the developer must want to invalidate the method. We called this condition a *cancellation*. Also, some methods aren't explicitly cancelled, but still don't work right. One example of a method that fails a lot is `at`, which is defined in `Object` but fails in most subclasses.

* For each class, tabulate its valid selectors. You should use browsers, but I encourage you to supplement your browsing by executing experimental messages like `Array new size` that will test whether the `size` method is supported by the `Array` class. It should take some time to do a thoughtful analysis. After you determine which classes support which selectors, arrange the classes into a plausible type hierarchy.

## 17.7 Solution and discussion

Here is what I found by snooping into these collection classes. Your results should be the same. In fact, because these classes are all standard Smalltalk classes, you should arrive at the same results no matter which dialect of Smalltalk you use. (The plus (+) means that the method is valid for the class.)

<table><thead><tr><th></th><th>size</th><th>at:</th><th>at:put:</th><th>includes:</th><th>&lt;</th><th>indexOf:</th><th>remove:</th><th>remove Key:</th><th>add:with Occurrences:</th></tr></thead><tbody><tr><th>Array</th><td>+</td><td>+</td><td>+</td><td>+</td><td></td><td>+</td><td></td><td></td><td></td></tr><tr><th>Bag</th><td>+</td><td></td><td></td><td>+</td><td></td><td></td><td>+</td><td></td><td>+</td></tr><tr><th>Collection</th><td>+</td><td></td><td></td><td>+</td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>
<table><thead><tr><th></th><th>size</th><th>at:</th><th>at:put:</th><th>includes:</th><th>&lt;</th><th>indexOf:</th><th>remove:</th><th>remove Key:</th><th>add:with Occurrences:</th></tr></thead><tbody><tr><td>Dictionary</td><td>+</td><td>+</td><td>+</td><td>+</td><td></td><td></td><td></td><td>+</td><td></td></tr><tr><td>Set</td><td>+</td><td></td><td></td><td>+</td><td></td><td></td><td>+</td><td></td><td></td></tr><tr><td>String</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td>+</td><td></td><td></td><td></td></tr></tbody></table>

To analyze the first column, I found that in IBM Smalltalk, Array, Collection, and String successfully inherit a size method from Object. But Bag, Dictionary, and Set don't. Instead, each overrides Object>>size with its own size method. Nevertheless, by one means or another, all six classes enjoy a working size method. Each class therefore gets a + in the first column. (In other dialects of Smalltalk, the size method comes from somewhere else in the class hierarchy, and different intermediate classes and can-cellations and reimplementations occur along the way. No matter. You will still find that all six classes enjoy a working size method.)

For the second and third columns I found that Array successfully inherits at: and at:put: from Object, and that Dictionary and String provide their own overrides. The other classes—Bag, Collection, and Set—inherit at: and at:put: from Object too, but the methods actually produce walkbacks. Thus only Array, Dictionary, and String get a + in the second and third column.

Continuing carefully in this way, I completed the rest of the table. Again, you should arrive at the same results from any standard dialect of Smalltalk, even though the details of your route may differ. From the table, we can propose a *type* hierarchy like the diagram below.

<figure><img src="image_123.png" /></figure>

Each type is labeled by the message selectors that pertain to it and its subtypes. Notice the fictitious type Locatable. This is a convenient type into which we can factor the selectors at: and at:put:, which service Array and Dictionary and their subtypes.
## 17.8 Exercise: Smalltalk's container "classes"

Consumers appreciate the type hierarchy above because it is easy to locate the classes they want to buy; it's an intuitive AKO hierarchy. Unfortunately, the hierarchy you see in Smalltalk is different. It's a producer's hierarchy—the beast—optimized for those who built it, not for those who hope to find its classes in intuitive locations.

* Use a browser to sketch the actual class hierarchy in Smalltalk.

## 17.9 Solution and discussion

The IBM Smalltalk *class* hierarchy we derive directly from a browser is:

<figure><img src="image_124.png" /></figure>

An innocent consumer, expecting an AKO hierarchy, is shaken by this one. Sets and bags are unrelated and arrays and strings have lost their intuitive AKO relationship. Why?

Sadly for the consumer, these classes were built by producers in ways advantageous to themselves. The consumer doesn't know it, but bags are built with dictionary-like objects inside them, so they don't need to inherit from sets. Strings are stored in a unique, compact way (remember the figure on page 195), so they don't inherit from arrays. And so on.

These internal design decisions, which the consumer doesn't want to know about, nevertheless affect the structure of the class hierarchy. Class hierarchies set AKO expectations for consumers, even if, as here, they are not AKO hierarchies. This is the unfortunate by-product of this chapter's theme: Smalltalk has only one hierarchy, which cannot serve two incompatible masters, subclassing and subtyping. The collection hierarchy you see through Smalltalk's browsers is a subclass hierarchy, not the subtype hierarchy you would wish to see. The type hierarchy is conceptually present, but for practical purposes it is invisible. We had to work hard to ferret it out.

Incidentally, the *class* hierarchy derived from a ParcPlace-Digitalk Smalltalk browser doesn't help, either:
<figure><img src="image_125.png" /></figure>

This hierarchy fails to capture the natural type relationships in an additional discon-
certing way—**Dictionary** inherits from **Set**. The producers chose this design for
implementation reasons: encapsulated within a set is an array, which dictionaries
inherit for their own private purposes.

An early exposé of the type versus class dilemma in Smalltalk appears in [LaLonde
et al. 1986]. For a thorough analysis of Smalltalk collection classes, see [Cook 1992].

17.10 Summary

Objects have outsides and insides. When we think that a square is well known to be a
special kind of rectangle, we are thinking of its customary behavior—its outside.
When we think that a square has just one side instance variable and a rectangle has
two, we are thinking about how they are constructed inside rather than how they
present themselves to their users. The sad truth about most object-oriented languages
today, including Smalltalk, is that they don't make the same distinction that our minds
do; they muddle subtyping with subclassing.

It is subtyping, not subclassing, that determines polymorphism. We can accuse
Smalltalk, with its typeless variables, of having an unusually forgiving type system
(look back at the table on page 206). Smalltalk enforces no discipline on the forma-
tion of type hierarchies, whereas other object-oriented languages go to great pains to
check type relationships for consistency.

As compensation, according to the first column in the table, Smalltalk supports
what we called implicit polymorphism (page 169). This polymorphism doesn't
depend on declared relationships between the classes. If two classes support the same
messages, they are consistent, even if they are in unrelated parts of the class hierarchy.
If **Puddle** and **CarBattery** both support **jump** and **drain**, Smalltalk regards them as
substitutable types, and so they may act polymorphically with respect to each other.
Looking back at our analysis of Smalltalk collections, **Bag** is a subtype of **Set**, so a bag
may be polymorphically substituted for a set, even though they are unrelated by inher-
itance.
## 17.11 Commentary: standardizing Smalltalk

Our analysis of the collection classes in the exercises above raises an interesting question: are the incompatible collection class hierarchies of the ParcPlace-Digitalk and IBM dialects a roadblock for standardizing Smalltalk? The ANSI committee's answer is a resounding "No." Its current approach to the problem is to standardize Smalltalk's type hierarchy rather than its class hierarchy. This is a progressive departure from the traditional Smalltalk mentality of subclass-based inheritance.

Notice how the ANSI approach fits with collection classes: I mentioned in the solution to the exercise that the result of the type analysis for the dialects is the same. That is, the collection *type* hierarchies from ParcPlace-Digitalk and IBM agree even though the collection *class* hierarchies don't. And it is the type hierarchy that matters to consumers. The type hierarchy represents their intuitive understanding of the behavior of objects, and it governs the objects they can use polymorphically in place of other objects.

A major attraction of any standard is the prospect of portable code. If we want to port our Smalltalk code from one ANSI standard dialect to another, we will have to follow one essential guideline when we write the code: we should only buy, not inherit from standard classes. By buying, we use only the standardized interfaces of the classes. On the other hand inheriting, even from standard classes, is sure to cause trouble because inheritance couples our subclasses to the nonstandard insides of classes (beast) instead of their standard outsides (beauty).

Also keep in mind that only part of an application is likely to be portable. The ANSI standard will focus on foundation classes—containers, magnitudes, streams, and so on. These are the basic building blocks for any Smalltalk application, but a real working application uses many other classes that are unlikely to be standardized. User interface classes are the first obvious omission because, as we know, these differ dramatically among vendors. But they are followed by persistence and database classes, communication classes, and so on. The best we can hope for is trouble-free portability of model code between standard dialects; the rest of an application will take work.
CHAPTER 18

Design patterns

Having now thought quite a bit about objects and programmed with them in Small-
talk, you are in a position to tackle a higher level of abstraction—design patterns. Pat-
terns occur in every activity; software isn’t special. A good chess player doesn’t think
through all possible combinations of moves; that is mathematically beyond reach.<fnref n="1" />
Instead, he draws on his mental respository of positions or *patterns* to limit the num-
ber of combinations he explores. Having this personal repository of patterns distin-
guishes the expert from the novice, whether the subject is chess or software.

Just as the chess player's patterns come from positions he has played plus ones
those he has studied in other games, the designer's patterns consist of those she has dis-
covered on her own plus ones she has seen in other people's designs. My purpose in
this chapter is to give you an edge by priming your personal repository of design pat-
terns with proven patterns from other people's designs.

Think of an object-oriented design pattern as a grouping of objects or classes that recurs in good designs.<fnref n="2" /> These groupings are signs of a natural evolution toward larger-scale reuse: in its early years, the object community focused on what made a good object or class, and now it turns to the question of what makes a good grouping of objects or classes. Our first example (page 215) is a pattern that has already occurred three times in this book, in the form of the **Account** and its transaction log, the **AddressBook** and the contacts in it, and the **ShapeRoom** and its shapes. This pattern is a *smart container*

<footnote n="1">¹ Even chess-playing supercomputers like Deep Blue, which won a game against world champion Gary Kasparov, use “patterns” to augment their raw computational power. For example, a computer might use a heuristic such as, “a castled king affords greater protection than an uncastled one.” *Heuristic* is a fancy word for a rule of thumb, which is also not a bad way to think of a pattern.</footnote>

<footnote n="2">² To some people, a pattern is or implies a great deal more. See the commentary at the end of this chapter (page 240) for an indication of these more profound understandings.</footnote>
because, for example, an address book contains contacts, but it is also smart enough to search by company or zipcode, to dial a contact's phone number, and so on.

The patterns in this chapter are ones I particularly enjoy. All designers have their own favorites, formed mostly of those that have helped them solve nasty problems. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides have organized twenty-three patterns into a catalogue, now a standard reference book [Gamma et al. 1995]. You will eventually develop your own idiosyncratic catalogue, based on the patterns that pertain to the problems you encounter.

Because these are *design* patterns, don't expect the Smalltalk code in this chapter to be entirely spelled out. A pattern is a reusable design, not reusable code. The descriptions include enough details to imagine how each pattern can help solve a problem, but to fully apply a pattern to your problem, you will still have to invest some of your own energies. In so doing, you will probably uncover variations on the basic techniques outlined here.

## 18.1 Notation

We need some notation to help convey the essence of a pattern. Here is an example of what we'll use, based mostly on OMT [Rumbaugh et al. 1991].

<figure><img src="image_126.png" /></figure>

The three-part rectangular boxes are classes; the top part is the name of the class, the bottom lists pertinent methods, and the middle contains pertinent instance variables. The triangle means inheritance and the diamond means aggregation. A dark circle indicates a *relationship* or *association* that involves possibly many instances of a class, such as the many instruments in an orchestra above. When we need to depict the logic of a method, we'll use a rounded box, as for *Violin>>play*. And we continue to mark subclassResponsibility methods with asterisks, as we have done since Chapter 5.
These notations are a far cry from a full-bodied design methodology notation, but they are enough to get us started.

I mentioned in Chapter 6 the gray area between aggregations and containers. A similar gray area exists between aggregations and one-to-many or one-to-one associations. An aggregation is a particularly strong kind of association, one in which the designer feels that “part-of” is an apt description. But what one designer calls an ordinary association, like the one-to-many relationship between orchestra and instruments illustrated above, another may choose to call an aggregation. This second designer would have used the diamond notation to indicate that instruments are part-of an orchestra, or an orchestra has instruments.

Two designers could also quibble over the relationship between orchestra and conductor. One could argue for an ordinary one-to-one association; the other for the more special aggregation, as illustrated above. These are judgment calls. The decisions are influenced by the problem you are solving (which doesn’t help here because I have not yet presented any problems).

For example, a problem on simulating a conductor’s schedule and duties might warrant reversing the relationship entirely and declaring that a conductor has an orchestra:

<figure><img src="image_127.png" /></figure>

These nuances remind us that design is an inexact craft, but they won’t matter for this chapter. We need notation only to illuminate concepts and avoid ambiguities.

## 18.2 Smart container (aka collection-worker)

Let’s begin on familiar ground, by reviewing the common design for a checking account, an address book, and a shape editor. They all look like this:

<figure><img src="image_128.png" /></figure>
Class Account is conceptually like a container, because it “contains” transactions, yet it is smart in the sense that it processes transactions and adjusts its balance. The actual container is a built-in container from Smalltalk, in that case an instance of Sorted-Collection. Similarly, class AddressBook basically contains person objects, but it has behavior (for managing contacts) that goes beyond what any of Smalltalk’s built-in collection classes can do. And class ShapeRoom conceptually contains shapes, but it can move them around and even undo the user’s actions.

In all three examples, the job of adding, removing, and holding on to the pertinent items goes not to the smart container but to some built-in Smalltalk collection class. The smart container only appears to contain its items. Peter Coad calls this “the fundamental pattern” or the collection-worker pattern; it is the base for most of the patterns in his book [Coad et al. 1995].

## 18.3 Reification

Reification is a broad term that means to turn something that doesn’t seem to be an object into an object. It is so broad that it is not quite fair to call it a design pattern. If anything, it is a meta-pattern, out of which other design patterns emerge.

The most striking examples of reification occur when the designer treats a method or verb-like idea as an object. You have seen a classic example in the undo exercise on page 176, where commands or actions became classes of objects. We will revisit this particular reification in the next section.

As a matter of fact, any time an activity or behavior starts out as a method, but over time you sense that it has rather complicated variants, then that activity is a good candidate for a class, and the variants are candidates for subclasses. That is what happened in the undo situation. Specific kinds of actions—moving, creating, and removing—became subclasses. We reified each operation into a class of its own.

Another common example is searching. At first blush, searching a repository of objects is plainly a job for a method. But pretty soon one realizes that the act of requesting a search can be a rich activity; there may be all manner of ways of specifying a search. This discovery leads pretty quickly to reification: one defines a class called Search with instance variables that represent the various arguments describing the criteria for a search. A search object immediately becomes handy if you want to search again, with slightly different criteria. And the next thing you know, you want to search for different kinds of objects in different repositories, so you define separate subclasses of Search for each such kind of object. The innocuous verb-like act of searching has blossomed into several potential classes.
You'll notice that once you reify something into a class, its principal public method often turns out to have a really routine name, like **undo** for the **Command** class. In the **Search** example, the name is likely to be **execute** or **doIt**. The method then gets reimplemented polymorphically in each concrete subclass so that every kind of **Command** knows how to **undo** itself and every kind of **Search** knows how to **execute** itself. This observation illustrates a rule of thumb: *reification begets polymorphism*. Whenever you reify from a method to a class, you are likely to enjoy the benefits of polymorphism.

Although the most dramatic reifications start from a method, not all do. One common form starts from a relationship between two classes of objects: introducing a **StudentCourse** class to manage the intricacies of the many-to-many relationship between **Student** and **Course** classes counts as a reification. For example, grades and attendance are better encapsulated within an instance of **StudentCourse** than within either an instance of **Student** or **Course**. This form of reification is known as an *association class*, and information such as grades and attendance are known as *link attributes* [Rumbaugh et al. 1991].

Reifications can also start from larger-scale activities than a method. For example, [Jacobson et al. 1992] suggest that an entire use case can be an appropriate candidate for an object. When they reify an activity, be it a whole use case or a more modest activity, they call the resulting object a *control object*. In other words, a control object is a reification of an activity. (These control objects should not be confused with the controller objects of MVC.)

In general, reifications exhibit the evolution of a design from plain beginnings to object-oriented respectability. A draw method eventually becomes a **DrawingTool** class; a conversion method for translating, say, an MM/DD/YY string format into a date object eventually becomes a **Converter** class (**AbtConverter** in VisualAge); operations for copying bitmaps eventually become the **BitBlockTransfer** class (**BitBlt** in VisualWorks); and so on. The essential lesson of reifying is that when things start to get complicated in a design, the experienced designer steps back and considers the possibility of introducing a brand-new kind of object. One can almost say that reification is object-oriented design. As you study the command pattern again, look at it in this spirit.

## 18.4 Command

You have solved the undo problem before; now let's cast it into the form of a pattern—the *command* pattern.

* How would you complete this design for undoing actions or commands?
<figure><img src="image_129.png" /></figure>

**Solution:** We review the earlier discussion (beginning on page 177), using now different names. Both `Command>>execute` and `Command>>unExecute` are subclassResponsibility (pure virtual) methods in the `Command` class, and they have concrete realizations in each of `Command`'s subclasses. To maintain a chronology of the command objects, we need a `Stack` class. A `Stack`'s LIFO (last-in-first-out) policy ensures that the most recent command will be undone first. The result is:

<figure><img src="image_130.png" /></figure>

Not only does this illustrate the command pattern, but you should appreciate that formulating a `Command` class in the first place is an archetypal example of reification. The crucial discovery of the undo solution was to accept that so verb-like an idea as *move*, or *remove*, or *command* is, for the undo problem, an object.
## 18.5 Factory method

It often happens that one class depends crucially on another for certain services. For example, in a client/server system, the class that transfers customer data back and forth between a database server and a Smalltalk client (typically called the **CustomerBroker** class) needs the **Customer** class whenever it creates a new customer object. Or a **Calculator** class in an office desktop application needs a standard **CalculatorWindow** class when it presents itself on the screen.

Early in an application's life cycle, the designer inevitably realizes that other pairs of classes have the same relationship: **OrderBroker** needs **Order** when it creates a new order object, or **Phonebook** needs **PhoneWindow** when it presents itself. This situation often leads to code that looks like this:

<figure><img src="image_131.png" /></figure>

Notice the small but troubling redundancy: the messages **...new openWidget** appear twice, in exactly the same form.

* This redundancy calls for a simple but dramatic improvement. We should try to factor the common **...new openWidget** code out of the subclasses and elevate it to the superclass **DesktopObject**. But how?

**Solution:** Just write the code for **DesktopObject>>openWindow** in the only way that makes sense: **self windowClass new openWidget**. Here the **windowClass** method must be deferred to the subclasses. That is, each subclass must support a **windowClass** method that returns its associated class. The result is:
<figure><img src="image_132.png" /></figure>

This pattern is known as a *factory method*, mainly because it frequently occurs when an object manufactures an instance of an associated class. Note the pattern's minimalism: each class and each method does only what it makes sense for it to do, and no more.

This pattern is an excellent indicator of the quality of any design involving abstract classes. It occurs in the life of a design only after the designer has spent some effort architecting clean relationships between classes. Conversely, if you don't see the pattern anywhere, it can be an indication that classes and their relationships have been haphazardly laid out.

## 18.6 Objects from records

The *objects from records* pattern is more specialized and intricate than the others in this chapter. It solves today's most fundamental client/server problem, moving back and forth between typical flat, relational databases on a server and objects at a client workstation.

A record, as programmers have always understood it, is simply a string of bytes that is subdivided into distinct fields. Historically, records were strips of data fitting end to end in a file or a "dataset." Today we commonly encounter records in the form of rows of a relational database table. Sometimes, in complex client/server applications, the bytes in a record may be assembled at the server from several database rows or other sources. But no matter where the data comes from, the essence of a conventional record is still just a string of bytes:
<figure><img src="image_133.png" /></figure>

Although there is nothing novel about a record, it is so much an intrinsic part of a typical server that it (or something like it) must play a leading role in any mechanism for exchanging data between a server and an object-oriented client. Historically, programmers first solved this problem by translating each field in the record into a corresponding instance variable:

<figure><img src="image_134.png" /></figure>

This translation generally occurred as soon as the record arrived from the server, and it was performed sometimes by the Customer and sometimes by another object (such as a CustomerBroker). The record had then served its purpose and became an unwanted appendage.
This approach had some drawbacks. It is always important in an object-oriented design to distribute behavior into the classes for which the behavior makes most sense. That a business object class like **Customer** is responsible for translating low-level byte representations into objects exceeds our normal expectations of a “customer.” A “broker” is a somewhat better candidate, but a broker ought to focus on locating and retrieving information from wherever it happens to reside, whether a local database or a remote server, which is a different function than translating between byte representations and objects.

Moreover, the “record” object’s role is so passive that it hardly deserves to be called an object. We like our objects to have interesting behavior, and the record above is merely an inert data structure. All these drawbacks repeat in the opposite direction when the application needs to send an updated customer object back to the server. As an additional difficulty, users sometimes decide not to proceed with an update but would rather restore the customer object back to its original state. Since an instance variable can’t hold two values at the same time, the original one and the updated one, this design doesn’t maintain enough information to revert the customer object.

The pattern *objects from records* addresses these drawbacks by making the record an integral part of the customer object and also giving the record the responsibility for translation. The record objects will resemble a traditional record, but will be quite a lot smarter. In its simplest form, the record object encapsulates the data, its layout within the record, and the conversion or translation between bytes and objects. A customer object doesn’t even need instance variables. Of course, it still needs `getter` and `setter` methods, but these can communicate directly with the underlying record instead of with instance variables. The design looks like this:

<figure><img src="image_135.png" /></figure>
"Mapping information" consists of the bookkeeping needed to map names of fields like `#address` to positions and lengths in the byte array. "Conversion information" is the information needed to convert each field of the record to and from primitive objects such as strings and integers.

That summarizes the basic pattern. For the reader who is interested in the details, here is a closer look at class `Record` and its collaborators. In addition to a `ByteArray` that contains its original raw data, we may as well cache the results of each field conversion if and when a conversion occurs. The cache saves having to convert again if the field is accessed a second time. It also provides a serendipitous slot in which an updated value may be stored via `Record->at:put`. If the user commits the update, the cached values are copied onto the original byte array, and if the user reverts or rolls back, the cached values are simply cleared.

Thus, a more complete design is:

<figure><img src="image_136.png" /></figure>

You should consider this pattern for any client/server application involving a non-object-oriented server. It decouples problem domain objects from server data structures and minimizes the overhead of converting to and from objects. The basic form may be embellished in several practical directions. For example, you can automate the generation of getters and setters, or you can automatically generate record maps from whatever defines the records—COBOL copybooks, C structures, or SQL statements. And if you lament the absence of instance variables—which you shouldn't too deeply,
since the essence of an object is its behavior rather than the particulars of how it stores its data—you can resurrect them for use as a cache; conceptually this amounts to transplanting the cache from the record object to the business object.

This pattern may become obsolete someday, if legacy relational databases vanish and object-oriented distributed computing becomes common through facilities like the Object Management Group's specification for distribution (CORBA) or object databases (such as GemStone, ObjectStore, Tensegrity, and Versant). In the meantime, *objects from records* remains a fast, clean way to exchange information among computers across a network.

## 18.7 Proxies and ghosts, I

A *proxy* stands in the place of an actual thing. Proxies, like objects from records, occur in client/server designs. That's because an object, or even more to the point, a collection of objects, may be quite large, and it may be impractical to materialize the entire object or collection from the server. Instead, the client manipulates proxies for the objects, and only if the user needs the whole object does the application materialize it. Now, when the object finally does materialize, its proxy may behave in one of two ways. It can either forward messages to the object, so that in effect the proxy is transparent, or it can transform (or "morph") itself into the object, so that the proxy disappears. We'll discuss the second kind of proxy in the next section.

The first kind, sometimes called a *handle-body*, looks like this:

<figure><img src="image_137.png" /></figure>

The "handle" is the proxy and the "body" is the customer. The hollow circle means that the proxy has either zero or one customer object, depending on whether or not its underlying customer object has been materialized.
What should the code for the method `CustomerProxy>>address` do?

**Solution:** It should check to see if the **Customer** has been materialized, and if not, it should materialize it. Then it should forward the **address** message on to the **Customer**, like so:

```
address
    "Answer my address"
customer isNil
    ifTrue: [customer := "materialize the customer"]
    ^customer address
```

This trick of initializing an instance variable only at the moment you discover you need it is known as lazy initialization. One hopes that most customers will not be needed by the client, and so the space and time for materialization will occur for relatively few customers.

Finally, how does the proxy know the right customer to materialize? It must know one more crucial tidbit, namely, some key that identifies the customer for which it is the proxy. This key is generally a unique identification number stored with each customer in the server database. The full design is then:

<figure><img src="image_138.png" /></figure>

As a crowning touch, we have remembered to add subclassResponsibility methods to the abstract class. Although not mandatory in Smalltalk, it is always a good practice to use them to indicate that the programmer must provide a concrete overriding method in each subclass (page 64).
## 18.8 Proxies and ghosts, II

The second kind of proxy is called a *ghost*. Consider this diagram:

<figure><img src="image_139.png" /></figure>

As for any proxy, the ghost must contain at least enough information in the instance variable `id` to uniquely identify the object it represents. `Object->doesNotUnderstand:` is the familiar error message that executes whenever a message is not understood by an object. The essence of the ghost pattern is for the ghost to override this error.

* Unlike the handle-body proxy in the previous section, the ghost does not support an *address getter*. What then should it do if it receives the message *address*?

**Solution:** Normally, the inherited `doesNotUnderstand:` would execute, and a walk-back would follow. To provide a more satisfactory response to the *address* message, we override the usual `doesNotUnderstand:`. Instead of announcing an error, this version of `doesNotUnderstand:` will begin by materializing the customer. With a customer object now in hand, a conventional handle-body proxy would merely redispatch the *address* message to the customer.

But this being Smalltalk,<fnref n="3" /> we will do something extraordinary: we will transform (morph) the ghost into the customer. That is, the ghost object of a moment ago will become an entirely different kind of object, namely the customer object. To morph an object in Smalltalk, we will need a special method named `become:`. Finally, we'll redispatch the *address* message to self, which by this time refers to the customer and not the ghost.

<footnote n="3">³ This is the only Smalltalk-specific pattern in the chapter.</footnote>
The method in its entirety looks like this:

```python
doesNotUnderstand: aMessage
    "I, as a ghost, do not support aMessage. I will materialize a
    customer, morph myself to it, and then try aMessage again."
|customer|
customer := "materialize the customer"
self become: customer.
^aMessage sendTo: self. "re-dispatch!"
```

Note how the redispatch in the last line treats `aMessage` as an object. In Smalltalk, everything is an object, including messages. Even in other dialects, where the form of the redispatch varies slightly, the essential truth remains intact: a message is an object too.

The overall pattern is:

<figure><img src="image_140.png" /></figure>

The happy outcome of all this activity is that where there was once a ghost that understood nothing, there now stands a customer that understands `address`, `name`, as well as every other customer message. Thus all future message sends will be successfully and immediately handled by the customer.

**Technical note:** It is only fair to say that this attractive design can have one drawback. In some Smalltalk implementations, where objects refer directly to other objects rather than through a table of object pointers, `become`: can be much slower than the virtually instantaneous method executions you are accustomed to. The degradation occurs because the virtual machine must locate all references to the ghost and reset them to point to the customer. You should therefore run some simple performance tests before adopting this pattern.
## 18.9 Dependency (aka broadcasting, model-view, observing, publish-subscribe)

Remember that in a well-designed user interface, views are directly aware of models, but not conversely. All a model can do is broadcast **update** messages to its views (or more generally, to its dependents), and the views then issue any specific inquiries to the model that they deem appropriate. This lopsided communication recurs often enough in object-oriented systems that it warrants recognition as a design pattern, called the *observer* or *dependency pattern*. In the model-view situation that you are most familiar with, views are the *observers* or *dependents*, and models are called *subjects*.

Here is the basic scenario:

<figure><img src="image_141.png" /></figure>

In Chapter 11 we discussed a variety of ways to implement the dependency relationship. The model may have a concealed instance variable, or there may be a shared dictionary somewhere that maintains the dependents of every model in the system. The specific implementation is unimportant for this discussion. By whatever means, the view receives an **update** message.

### ☐ What should update do?

**Solution:** It should query the model for the values it cares about and then reflect these possibly changed values into its display, roughly along these lines:

```python
update
    "Obtain current data, then redisplay myself"
    model getValues "and process them".
    self repaint.
```
The result is:

<figure><img src="image_142.png" /></figure>

As we learned in Chapter 11, the essential benefit of this pattern is that the model functions independently of the number and kind of views. Models then can represent the conceptual objects of the problem without being burdened by user interface considerations. Views, on the other hand, concentrate on rendering information. They know their models and how to extract the information they care about from them.

Notice that “observer” is a misnomer for view or dependent because modern views, in absorbing the additional responsibility of MVC controllers (Chapter 11), are not just read-only objects. They respond to user inputs and may set values in their models as well as get them. However intrusive this “observation” is, models remain oblivious to their views, which is the most important theme of the pattern.

In general, the dependency pattern is the right way for an object to notify unknown numbers and kinds of other objects (its dependents) about changes in its state. For example, a traffic light simulation might notify all vehicle objects that it has changed to green. Or a palace vault might broadcast an alert to various security devices and stations if its entry has been breached. In fact, the whole idea of event notification, such as an operating system notifying windows that a mouse event has occurred, fits into the scheme of this pattern. (Also, with all broadcasts it is reasonable to pass some information along as an argument, such as the coordinates where the mouse event occurred, or a severity indication like “this event is a dire emergency.”)

In the pattern's sharpest form, the broadcast consists of an arbitrary cluster of messages, with different clusters triggered by different events. See page 120 for a discussion of this form of the pattern.
## 18.10 Solitaire (aka singleton)

A computer should hold no more than one instance of some kinds of objects. Examples include objects that manage resources such as windows, or memory, or time. Another example, from distributed or client/server applications, is a broker object which obtains objects from the server and keeps track of those it has already obtained.

The problem is to design the protocol for constructing and accessing an instance of a class in a way that minimizes the possibility of inadvertently constructing a second instance. Here, for example, is an undesirable solution:

```
TheBroker := Broker new.
...
TheBrokerwisid: '1234'.
```

For one thing, we have introduced a global variable *TheBroker*, and global variables are as a rule a bad idea. Global variables present the temptation of writing, elsewhere in the application,

```
OnlyBroker := Broker new.
```

which creates a second broker, or just as disastrously,

```
TheBroker := Broker new.
```

which loses the first broker together with its knowledge of objects it has already obtained from the server.

The *solitaire pattern* eliminates the global variable and its risks:

<figure><img src="image_143.png" /></figure>

What should you write to obtain an object from the server?

*Solution:*

```
Broker instanceSTAid: '1234'.
```

Lazy initialization in the class method named *instance* assures us of the same instance of *Broker*, whether this request is the first or a subsequent one. As an additional precaution against accidentally creating brokers, note that the *new* method has been disabled.
Typical client/server systems involve more than one class of objects. Because the logic that materializes each class of objects may differ, or different classes may require different servers, it is usually appropriate to define a separate broker for each class. **Broker** is then an abstract class with specific broker solitaires like **CustomerBroker** and **AccountBroker** as subclasses.

*Technical aside:* When **Broker** has subclasses, a class variable for the **One** is not as suitable as a Smalltalk *class instance variable*. Each subclass inherits its own separate, unshared copy of a superclass's class instance variable, in which the subclass's separate broker may reside. Class variables don't have this property. Instead, all subclasses share a class variable defined by their superclass—not very helpful if you want each to have its own separate broker.

## 18.11 Duet (aka pas de deux, double dispatch)

Those few occasions when a "function" just doesn't seem to be a method on a single object, but rather ought to be a "method" on two peer objects, can cast the whole applicability of object-oriented programming in doubt. Our modern, object-centric view of the world is too narrow for these situations.

For example, is **play** a method in class **Instrument** that takes a **Musician** as an argument? Or is it a method in class **Musician** that takes **Instrument** as an argument? Or is it something else, an operation on a *pair* of objects? If the situation calls for an operation on a pair of objects, we use the *duet* pattern. The most interesting application of this pattern occurs when **Instrument** and **Musician** both have subclasses, because **play** then becomes an operation that is polymorphic on both of its arguments. (Refer to the commentary on multi-methods on page 170 for an example and discussion.)

A basic example of duets is arithmetic, where the asymmetric interpretation of $a + b$ (a receives the message; b is "just" an argument) rattles Smalltalk newcomers. From our earliest functional schooling, we developed faith in the symmetry of the operation $a + b$. We psychologically want addition to be an operation on two objects—a multi-method—rather than a message to one of them. But Smalltalk, being a "pure" object-oriented language, cannot oblige.
Only CLOS among commercial object-oriented languages supports genuine multi-methods. In Smalltalk we can synthesize an arithmetic multi-method with this duet:

<figure><img src="image_144.png" /></figure>

You can use `+` to add an integer and a float in either order. But only one of them—the `Float`—can do the real work. If the other—the `Integer`—is asked to do the job, it automatically sends a message to the `Float`, announcing that it is an integer seeking assistance from the `Float` to do the arithmetic.

This pattern is a "duet" because it makes the participants seem like peers. It is a *double dispatch* or *pas de deux* because of the dramatic transfer of control and passing of self as an argument to the other object.

For the programmer who implements the pattern, the important outcome is the elimination of conditional tests. The integer does not check anything; it immediately and unconditionally sends the message to its argument, announcing that it is an integer in need of aid. As we've learned from studying polymorphism, one of the best ways to simplify software maintenance is to write code without conditionals.

For the consumer programmer, the important outcome is conceptual simplification: it doesn't matter which of the two objects he sends the `+` message to. In effect, `+` is, from his perspective, a non-object-oriented operation. It also doesn't matter what types of objects participate in the operation. He can add any combination of `Float`, `Integer`, or `Fraction` without a second thought.

* What happens if the `+` message is merely used to add two integers together, rather than the more complicated scenario of an integer and a float?

**Solution:** `sumFromInteger:` still executes unconditionally, but it is now sent to an `Integer`, so the `Integer` class had better implement `sumFromInteger:` as well. Fortunately, this is a reasonable expectation—an integer ought to be able to add another integer to itself.
Although duets are a clean way to implement arithmetic, and VisualWorks and to a lesser extent VisualSmalltalk use them for arithmetic, IBM Smalltalk does not. For speed, IBM Smalltalk implements arithmetic directly in its virtual machine.

## 18.12 Lawyer (aka object handler)

Often, two kinds of objects work together, but neither should be complicated by direct knowledge of the other. We have seen this situation in many-to-many relationships (page 217), and we are now about to see it in one-to-one relationships.

Consider an icon object and the model object that it stands for. In the spirit of model-view separations it would be unseemly to give the model object knowledge of a visual object like its iconic representation. Also, an icon is such a simple visual object—roughly a bitmap—that we would not expect it to know how the user interface happens to associate some model object with it.

We wish to decouple the two objects, yet on the other hand we would like to keep the model informed about the icon's experiences. For example, if in a graphical editor the user drags an icon representing a graphical element to a different location, we would expect the coordinates of the graphical element to change. Neither the icon nor the graphical element alone has this responsibility. So we construct a third object, called an *object handler* or *lawyer*, which knows both the icon and the graphical element [Collins 1995].

The user interface then manipulates lawyers instead of icons. Through lawyers, the user interface can communicate indirectly with either party a lawyer represents, be it the icon or the underlying object. The pattern looks like this:

<figure><img src="image_145.png" /></figure>
Updating the coordinates of a graphical element is a relatively simple service of one lawyer—the lawyer merely mediates between the icon and the graphical element. This lawyer is an example of the *mediator* pattern [Gamma et al. 1995]. Lawyers make especially good livings by talking to other lawyers; this is the relationship we examine next.

Consider icons again. The usual visual feedback that occurs as a result of dragging one icon over another depends only on the types of the objects represented by the icons. For example, the feedback will indicate that you cannot drop a file icon onto a calculator icon, but that you can drop it onto a printer icon. This has nothing really to do with the underlying objects; the user interface can compute the feedback from the icons alone. But suppose a sophisticated user interface must provide more refined feedback, such as an indication that you cannot drop a file icon onto a printer icon if the printer object is off-line. This feedback depends on the state of the underlying printer object and therefore cannot be determined solely from the icons.

What objects can make this determination?

**Solution:** We have ruled out the icon objects, since they are oblivious to the state of their associated objects. But lawyer objects can make the determination because they know about the icons (is the file icon over the printer icon?) as well as the underlying objects (is the printer on-line?). Thus the file lawyer can negotiate with the printer lawyer to determine the appropriate feedback. Here are the relationships and responsibilities:

<figure><img src="image_146.png" /></figure>
Let's step through the interactions. Suppose the user has positioned the file icon over the printer icon. Since the user interface manipulates lawyers rather than icons, it asks the file lawyer whether it is droppable on the printer lawyer. To answer the question, the file lawyer asks the printer lawyer whether it is a valid target, which the printer lawyer in turn determines by asking its subject the printer whether it is on-line. Depending on the response, the user interface will display either a "cannot drop" or an "ok to drop" indication.

Without delegating the negotiation to the two lawyers, we would have had to write and maintain messages flowing directly among all four principal parties—two icons and two model objects. Lawyers simplify the interactions in direct manipulation user interface designs just as observers or model-view separations simplify the interactions in windowed user interface designs.

This pattern is not just about user interfaces. The essential lesson is that whenever two objects are in one-to-one association with each other, the association becomes a prospective object in its own right. This object—a lawyer—reifies the association. In our example, the lawyer reifies the association between an icon and the object the icon represents. The striking additional twist in our example is that two lawyers can go on to negotiate with each other.

## 18.13 Composite

The composite pattern is the workhorse of recursive relationships. Whether you are nesting graphics or exploding a bill of materials or processing a parse tree, the composite lets you apply some operation to every object or node in the structure.

Suppose you want to calculate the cost of a complex product like a telescope. The telescope consists of a basic scope and an eyepiece. In turn, the basic scope consists of a tube and an objective lens, the lens has glass plus a sophisticated fluorite coating.... We can represent any such product with this recursive design:

<figure><img src="image_147.png" /></figure>
The picture shows us that a compound product consists of any number of other products, each of which could be either atomic or another compound product. Product is an abstract class. It cannot calculate its cost and it has no instances. Atom is usually also an abstract class; in our example, it has irreducible subclasses like FluoriteCoating, each of which can calculate its own cost.

* What is the Smalltalk code for `Compound>>cost`?

*Solution:* The instance variable products is a collection (say, an OrderedCollection), so cost should simply iterate over each product in the collection, ask it for its cost, increment a total, and respond with the final total. The entire pattern is thus:

<figure><img src="image_148.png" /></figure>

The composite pattern is simple and elegant. What helps account for its appeal is how the polymorphic cost method acts in a different but unimpeachably apt way for each class.

The composite pattern is the basis for more specialized patterns, such as the next one.

## 18.14 Visitor

The visitor pattern blends features from two of the preceding patterns, namely the duet and the composite. The composite pattern is attractive as long as the action that must be performed at each node is a straightforward polymorphic message like cost above. When the action shows signs of blossoming into a complex method involving other far-reaching objects, the composite solution loses its appeal.

Problems having to do with language translation or program compilation fall into this category. As a translator iterates through the nodes of a parse tree, it may require knowledge about a foreign language. This knowledge probably isn't encapsulated within the parse tree. A node object from an English sentence knows its syntactic role in English, but shouldn't have to know about foreign words and syntax.
Here is a sample problem. Bear with me while I remind you about some grammar lessons from school. The first thing a translation program does is the same thing you did when you diagrammed sentences. It generates a parse tree.<fnref n="4" /> The sentence, "The cat chases a dog," results in this parse tree:

<figure><img src="image_149.png" /></figure>

We want to eventually produce the French sentence, "Le chat poursuit un chien," from this tree. Each node in this tree is an object, but they are instances of several classes. The leaf nodes along the bottom row are called **Terminal** nodes. Thus there are three subclasses of **Terminal**, namely **Article**, **Noun**, and **Verb**. The non-leaf nodes are **NonTerminal** nodes. The subclasses of **NonTerminal** are **Sentence** and **NounPhrase**. The inheritance hierarchy for these classes looks enticingly like a composite:

<figure><img src="image_150.png" /></figure>

<footnote n="4">⁴ There are many ways to generate a parse tree, the simplest of which is known as recursive descent. The mechanics of generating a parse tree by this or any other means will not concern us; we are interested in what you can do *after* you have the parse tree.</footnote>
But if we try to apply the composite pattern, recursively sending a **translate** message to each node object, we face the drawbacks alluded to above. First, the tree is an English parse tree, and its nodes shouldn't have to know any French. (If they did, the design could not be reused for translating English into, say, Chinese.) Second, translation is more subtle than just translating leaf nodes one by one. Translating the noun *cat* to *chat* affects the translation of the preceding article *the*—the gender and spelling of *chat* imply that the result should be *le* (and not *la* or *l'*). Unfortunately by the time the **translate** message arrives at *cat*, the preceding word has already been translated. To translate correctly, we evidently must involve the **NounPhrase** class, and if we insist on using the composite pattern we will have to add complex, French-specific logic to its **translate** method.

* How can we decouple these French-specific complications from the English-based node classes?

**Solution:** Invent a new class that reifies the **translate** method. That is, instead of writing a complex, French-specific **translate** method on each node, define a class called **Translator**. An instance of **Translator** visits each node. Upon each visit, it is asked to perform some operation, which is why the pattern is called a **visitor**. It looks like this:

<figure><img src="image_151.png" /></figure>
The burden of translation has been lifted from the humble node and placed on the back of the able-bodied visitor. **Translator** will have an instance variable for storing a language-specific translation dictionary. The complex **translate** method has been replaced by the **visitBy**: method, which merely dispatches a message back to a translator object, passing **self** (the node) as an argument. The translator object can then do whatever it wants with the node. Any complex logic, such as translating the gender and article of a noun phrase, resides in the translator instead of the nodes of the parse tree. Note the similarity to a duet: the message to the translator announces the type of object being passed (**translateNounPhrase**: or **translateVerb**:), just as our duet did (**sumFromInteger**:).

This pattern also makes other translator classes feasible (**EnglishToFrench**, **EnglishToChinese**...). The English parse tree doesn't change at all; to translate to another target language, the parse tree's nodes are simply visited by a different translator. The visitor pattern neatly factors behavior into classes for which the behavior is most suitable. By not cluttering the parse tree with extraneous information, it is easier to reuse for other language translations. The visitor pattern is a fitting finale to this chapter because it extends two fundamental patterns—the composite and duet—and illustrates again the value of reification.

## 18.15 Conclusion

Since there are infinitely many ways to group objects or classes, it's not constructive to call every grouping a pattern. A grouping deserves to be called a pattern only if doing so is useful for designers. As for what constitutes "usefulness," here are some informal criteria:

* The grouping is based on metaphor(s) or other recognizable ideas. This, together with the next criterion, helps designers remember the pattern.

* The grouping has an evocative, memorable name. Among object-oriented designers, pattern names are a lingua franca for quickly exchanging ideas about how to solve a problem, or understanding how a piece of software has been structured.

* The grouping resembles a micro-architecture. In other words it is not an ad hoc assemblage of objects, but an assemblage that conveys a coherent sense of function, structure, and aesthetics.

Once you know a few design patterns, you will start to recognize opportunities for applying them. It's like a chess player who studies openings or a guitarist who learns a few chords. Sooner or later they are likely to have an opportunity to use them.
Here is a summary of the patterns we've studied:

<table><thead><tr><td>Applicability</td><td>Pattern</td><td>Sample problems</td></tr></thead><tbody><tr><td>Big object and small objects</td><td>Smart container</td><td>History log, address book, ...</td></tr><tr><td>Heavy verbs</td><td>Reification</td><td>Converters, Search, Command, ...</td></tr><tr><td>Interactive applications</td><td>Command</td><td>Undo/redo</td></tr><tr><td>Redundant code</td><td>Factory method</td><td>One class routinely uses another</td></tr><tr><td>Flat or relational data</td><td>Objects from records</td><td>Client/server materialization</td></tr><tr><td>Too many large objects</td><td>Proxy and ghost</td><td>Remote computation</td></tr><tr><td>One-way observation</td><td>Dependency</td><td>MVC, alerts, events, callbacks</td></tr><tr><td>No more than one instance</td><td>Solitaire (singleton)</td><td>Brokers</td></tr><tr><td>Functions instead of methods</td><td>Duet</td><td>Multi-methods</td></tr><tr><td>One-to-one associations</td><td>Lawyer</td><td>State-based visual feedback</td></tr><tr><td>Nested objects</td><td>Composite</td><td>Drawings, bill-of-materials</td></tr><tr><td>Language translation</td><td>Visitor</td><td>Translators, code generators</td></tr></tbody></table>

You will find general treatments of all but smart containers, reification, objects from records, duets, and lawyers in [Gamma et al. 1995]. For more on smart containers, see [Coad et al. 1995]; for objects from records, see [Wolf and Liu 1995]; for duets see [Ingalls 1986]; and for lawyers (object handlers) see [Collins 1995].

## 18.16 Commentary: history

The idea of a software pattern can be traced as far back as the mid-1970s, when Adele Goldberg and Alan Kay at Xerox PARC realized that novice programmers couldn't solve hard problems, no matter how wonderful the programming language. The novices could comprehend the language well enough, but they couldn't be expected to know the design techniques that might be expressible in the language. This discontinuity is analogous to a child who can read and write English, but is too young to have digested the wisdom of great literature. To provide some conceptual building blocks above the raw language, Goldberg and Kay introduced *design templates*, which are a forerunner of today's design patterns [Kay 1993].

Kent Beck and Ward Cunningham discussed a small, potent set of software patterns in 1987 [Power 1988]. But the interest in patterns really burgeoned at Bruce
Anderson's architecture handbook workshop at OOPSLA '91.<fnref n="5" /> Articles on patterns began to appear a year later [Coad 1992; Eggenschwiler and Gamma 1992; Johnson 1992]. The landmark catalog appeared at the end of 1994 [Gamma et al. 1995]. Ralph Johnson organized the first conference on the subject of patterns in software in 1994 [Coplien and Schmidt 1995].

Software patterns have become so fashionable that they run the risk of overexposure. Just as almost anything may be construed as a metaphor (page 146), almost anything may be construed as a pattern. Thus, many "patterns" are too narrow and arcane to be of much use to the general computing public, and many articles that would be interesting in their own right have been unnaturally cast into a pattern format. Nevertheless, plenty of promising, unexplored territory remains for patterns in software.

Before programmers got excited about software patterns, the architect Christopher Alexander and his associates published a series of books, starting with [Alexander et al. 1977; Alexander 1979], on the use of patterns to build living spaces for people. Alexander suggested that his catalog of 253 patterns could be a basis for everything from laying out a community down to deciding the décor for a room. His patterns, like good software patterns, are metaphoric ("City country fingers"), memorable ("Light on two sides of every room"), and architectural ("Perimeter beams"). His work inspired the early software-pattern investigators.

Alexander wanted to go far beyond merely applying proven patterns to the act of building. He wanted the resulting living space to have what he called, "the quality without a name." Patterns were just a means to this end. Unfortunately, this zen-like quality admits no definition. By and large, people agree on some few dwellings and communities that have the quality, and they agree that most dwellings and communities don't. It is the same with software. Programmers can generally agree that certain software is masterfully designed, but they encounter such software rarely.

In the years following publication of Alexander's books on patterns, he realized that patterns alone did not ensure that the results would have "the quality without a name." (He knew it as early as 1977, but the depth of the insufficiency became apparent only after disappointing experiments.) Revisiting the chess analogy: knowing and applying chess patterns improves one's game, but rarely does a beautiful chess game happen. The key to attaining this quality in software (or any endeavor) has not been discovered. For an appreciation of the depth of the problem as it pertains to rhetoric and philosophy, read [Pirsig 1974], and for a discussion of how Alexander hopes to solve it for architecture and what his ideas mean to software, see the series of articles [Gabriel 1993–1994].

<footnote n="5">⁵ OOPSLA is the annual conference on "Object-Oriented Programming, Systems, Languages, and Applications."</footnote>
CHAPTER 19

## Frameworks (one hearty example)

Object-oriented frameworks are as fashionable as patterns, and developers everywhere try to build them. Like patterns, so many things are now called frameworks that the meaning has gotten blurry, making it tough to appreciate their importance.

A framework is a general skeleton for a software application. More than one application may be built around the same framework, but they will all be shaped by the basic structures and mechanics of the framework, as though frogs of different appearances and appetites could be shaped from the same frog skeleton. To build frogs you use a frog framework; to build snakes you use a snake framework.

In technical terms, a framework is a body of code that is reusable across different projects. An example I've already talked about is the original MVC framework for user interfaces. MVC consists of the abstract classes Model, View, and Controller and the interactions among them. The most famous of these interactions are the broadcasts that a model issues. Practically every application developer in Smalltalk-80 reuses MVC by inheriting from one or more of these three abstract classes.

On the other hand, not every reusable library of classes qualifies as a framework. For instance, no one calls a library of container classes a framework, nor does anyone call a library of user interface widgets a framework. What's the difference? For one thing, a framework like MVC imposes a structure on an application, whereas a library of containers or widgets doesn't.

Another difference is what Erich Gamma calls the *Hollywood Principle*.<fnref n="1" /> “Don't call us; we'll call you.” Programmers are accustomed to writing calls to the functions in a library. (We say programmers call an *API*, for *application programming interface*.)

<footnote n="1">¹ Erich says that programmers at Xerox PARC coined this usage.</footnote>
The Hollywood Principle inverts this relationship: the programmer writes code that the framework calls. The programmer will have to know in advance what the framework is going to call—his code must conform to the framework's expectations. These being object-oriented expectations, the framework will include some abstract classes for which he builds subclasses and overrides subclassResponsibility (pure virtual) methods. Using a framework always involves subclassing from abstract classes; using an ordinary library of container or widget classes usually does not.

In other words, a framework specifies missing elements. When you supply these elements, the framework makes them operate together as a working application. By supplying different elements, you can create a different application. A framework provides all the machinery for an application except the application itself.

The best way to understand the idea of a framework is to study an example. We are going to tour some highlights of a framework that provides the machinery for developing client/server applications. This framework simplifies construction of Smalltalk applications that use non-object data from computers across the network. A framework like this one accounts for a substantial part of the overall effort in developing a client/server application; the cost and expertise needed to develop this support from scratch exceeds the cost of developing the application's model and view objects.

## 19.1 Problems

Any framework for supporting Smalltalk at the client and non-object data at the server must address some fundamental problems. You can think of these problems as the basic use cases of client/server computing.

*   **Materialization:** Transforming traditional, non-object data, usually in the form of records in a file or rows in a relational database, to and from objects that an object-oriented language can process.

*   **Identity management:** Ensuring that at most one version of an object resides at the client workstation. In other words, materialization should not produce a second copy of an object if the object has materialized once before.

*   **Searching:** Looking for one or more objects that match some criteria.

*   **Updating:** Changing the state of objects at the client workstation and cascading those changes back to the appropriate server. (The problem of creating a new object and saving it is similar.)
This drawing summarizes the problems:

<figure><img src="image_152.png" /></figure>

Imagine now that a programmer has been handed a client/server framework, and is developing an application for, say, bankers who watch over loans. We want to understand what he must do about each of the problems above. To understand what follows, you will need to know just a few facts about relational databases:

* Data are stored in tables. The columns or fields of a table have names, such as "LoanNumber," "OutstandingAmount," and "Collateral." And each row in a table contains related data, such as a specific loan's number, its outstanding amount, and its origination date.

* The standard language for manipulating relational data is SQL, the Structured Query Language. All relational database systems support dynamic SQL; a dynamic SQL statement must be reinterpreted by the database every time it is issued. Some database systems also support a form of pre-compiled SQL, which, once compiled, is bound to the database and can therefore execute faster than dynamic SQL. An example of this kind of SQL is IBM's static SQL for its DB2 family of database systems. (You won't need to know the details of the SQL language to understand this chapter.)

## 19.2 Materialization

The heart of any client/server application is materialization—the act of producing objects at the client workstation from some form of flat, non-object-oriented data at the server.

*What the framework does.* The framework uses the objects from records pattern (page 220) to convert flat data (records) to and from objects. An abstract class named
**BusinessObject** represents the objects produced by the pattern, and another abstract class named **Broker** encapsulates the algorithms for sending and receiving records to and from the server.

The design of a broker depends on the overall client/server architecture. One broker can issue dynamic or static SQL calls to the server; another can use a communication protocol like APPC or TCP/IP to issue calls to procedures or programs that execute at the server to process the data. In other words, some brokers are *SQL brokers* and others are *transaction brokers*. Because the private behavior of these brokers differs, the framework has different abstract classes for them. (See the commentary on page 254 for more on broker varieties.)

Let's assume that the application designer decides to use the class of brokers that supports static SQL. The name for this abstract class is **SQLBroker**. This class collaborates with another abstract class called **DBPackage**, which houses the package of static SQL statements that gets bound to the database.

The framework must know that a specific combination of broker, package, and class of business objects works together—it won't do for a **LoanBroker** to try to materialize a **Customer** object, for example—so it declares subclassResponsibility methods named **Broker-->objectClass** and **Broker-->package** that link these classes.

*What the programmer does.* He builds concrete subclasses of the abstract classes, say **LoanBroker**, **LoanPackage**, and **Loan**, and links the classes with these methods in **LoanBroker**:

objectClass
  "Answer the class of business objects I broker"
  ^Loan

and:

package
  "Answer the package of SQL statements I need"
  ^LoanPackage instance

The framework then ensures that these classes will work together correctly to materialize loan objects.

□ Explain the function of the **instance** message in the method above.

**Solution:** There should be only one instance of **LoanPackage** at the workstation. Packages are therefore solitaires (page 230) and **instance** is the (conventional) name of the class method that returns the unique instance of **LoanPackage**.
Here are highlights of the classes involved in materialization:

<figure><img src="image_153.png" /></figure>

You might recognize the methods `objectClass` and `package` as examples of the factory method pattern (page 219). The factory method is the bread-and-butter pattern of framework building.

## 19.3 Managing object identity

A built-in peril of client/server systems is the materialization of two separate objects that represent the same business object. This circumstance exposes the user to the risk of independently changing both copies, which would be a serious breach of object identity. (Remember the discussion of object identity, beginning on page 73.)

How could such a thing happen? Suppose a loan object materializes as a result of searching for all loans with more than $50,000 outstanding. Imagine that some time later a second search for all loans to some tycoon materializes the *same* loan. Unless the application was designed carefully, two loan objects at the client workstation now represent the same loan. To complete the misadventure, suppose the banker updates the wording of the collateral ("...log cabin, running water, screened-in porch...") in one and extends the payment terms in the other. Now neither loan object has the data the banker intended, and no matter which loan(s) are committed back to the server, confusion results.

*What the framework does.* A Broker contains a dictionary of all the objects it has materialized. Each entry in the dictionary has for its key a unique descriptor for the object and for its value the object itself. Thus if 100,000 loans are stored in the server
database, and the **LoanBroker** has materialized 29 of them, 29 entries will be in the **LoanBroker's** dictionary. Each of them consists of a key—probably the loan's loan number—and a value that is the loan object itself.

If the banker requests another loan object, the framework checks whether the loan's loan number is one of the 29 keys already in the dictionary. If so, it must not materialize another copy, for that would produce the unpleasant scenario above.

To make all this work, the broker evidently needs to know what to use as a key for its business objects. Therefore the **BusinessObject** class has a subclass**Responsibility method called `identityKey**. The broker uses this method to manage the entries in its dictionary, and in particular to determine whether a business object is already in the dictionary.

*What the programmer does.* He writes a method `Loan->identityKey` which simply returns the loan's loan number. The framework does the rest.

*What else the framework does.* The other side of the coin is cleaning up: when should the framework remove entries from the broker's dictionary of materialized objects? The framework can't afford to ignore removal because after prolonged use, a broker's dictionary of objects may grow so large as to overrun the workstation's memory. The challenge is for the framework to recognize when a business object is no longer needed by the application; that is, when no other business objects or views in the application refer to the object. At that moment the object can safely be removed from its broker's dictionary.

This challenge sounds suspiciously like a garbage collection problem (page 187). But not quite, for we have an additional, circular twist: the Smalltalk garbage collector won't recognize the object as garbage until the broker's dictionary releases its reference to it; on the other hand, the dictionary dares not release the reference until it knows that the object is garbage.

Fortunately, the latest major Smalltalk releases extend memory management with a feature called *weak references*. A weak reference to an object is a reference that doesn't matter to the garbage collector. Ordinary references are *strong references*; these are the references that the garbage collector uses to know that an object is still needed.

The idea is to design brokers to use weak references instead of strong ones so that the brokers don't stand in the way of the garbage collector. For this a broker must use a special dictionary known as a **WeakDictionary**—this and other collection classes whose names are prefixed by “weak” are the only kinds of objects that can refer weakly to other objects. The garbage collector doesn't care if a weak dictionary has a reference to an object; after all, it's not a strong reference but a weak one.

In the example above, suppose the weak dictionary has its 29 entries, each consisting of a loan number and the corresponding loan object, when the user decides to
close all views that are open on one of the loans. There are now no strong references to this loan object, but the one weak reference from the weak dictionary remains. Weak references don't stop the garbage collector; it considers the object to be garbage, reclaims its memory, and finally removes its reference from the weak dictionary. We have achieved the desired effect: by using the `WeakDictionary` instead of an ordinary `Dictionary`, the broker automatically releases an object once no application objects refer to it.<fnref n="2" />

*What else the programmer does.* Nothing more than the `identityKey` method he has already written, since all the logic of weak references in the `LoanBroker` will be inherited from `Broker`.

Here are the highlights of identity management:

<figure><img src="image_154.png" /></figure>

## 19.4 Searching (filtering)

Searching for things is a basic human activity. Sometimes we know exactly what we are looking for and we just want to grab it (the loan with loan number 334455), and sometimes we want to look at a collection of things (all loans with more than $50,000 outstanding).

<footnote n="2">² This problem has solutions other than weak references, but none are as satisfying. They all involve keeping track of references to business objects, which amounts to replicating the work of a garbage collector. A C++ version of this framework, lacking garbage collection, hence also weak references, would have no choice but to tackle this sizable and delicate job.</footnote>
*What the framework does.* Let's begin with the first case, where the user or application knows a key that identifies the desired object. The **Broker** provides a concrete method with a name like `objectWithKey()`, which takes the key as an argument and returns the business object having that key.

*What the programmer does.* He does *not* override `objectWithKey:` in his broker subclasses because the code can be written once with complete generality in **Broker**. On the other hand, he will find many occasions for invoking this method.

For example, suppose every loan object contains a customer number. That is, a loan object contains the key identifying the customer that took out the loan. While examining a loan, the user may want to also examine the customer. So the user clicks some button, and the programmer's code responds to the click by sending the `objectWithKey:` message, carrying the customer's key as an argument to the **CustomerBroker**, which responds with the customer.

Or the programmer may have designed proxies for customer objects (page 224 ff.), and imbued the proxies with getters that supply only enough information to display them in a list widget. By and by the user wants to see the full customer object behind one of them; this proxy then sends the `objectWithKey:` message to the **CustomerBroker**. Since the proxy knows the customer number for the customer it stands for, the message carries this key as its argument.

Here are the highlights of these two scenarios for grabbing full customer objects:

<figure><img src="image_155.png" /></figure>

The moral of this story is that frameworks not only demand that the programmer override subclassResponsibility methods, but they also make available concrete methods that the programmer will want to invoke. Notice that the programmer doesn't
need to examine any tricky code such a method may contain; he trusts that the framework got it right. Another way to say this, using some jargon, is that frameworks are characterized largely by *white-box reuse*, but they also provide some *black-box reuse*. (See page 253 for more on these terms.)

*What else the framework does.* The other kind of search sometimes goes by the name *filter*: the framework accepts a description from the user and filters the server for all the objects that match the description. This is an interesting problem for the framework designer because it is an opportunity to introduce two classes of objects that are not initially obvious. (Remember that such discoveries are known as reification. See page 216.) The first is an abstract class named *Search*; this class encapsulates the descriptions of the objects being sought. The second is *BusinessObjectList*, which is what a search returns.

Search objects solve a basic usability problem: after seeing the results of the search, the user often wants to adjust the description of the objects in some small way and search again. Because the framework retains the *Search* object, it is an easy matter for the user to access the original description, modify it, and reissue the search.

A *BusinessObjectList* is as good as an *OrderedCollection* for populating list widgets because it is designed to support the main methods of *OrderedCollection*—as far as list widgets can tell, a *BusinessObjectList* and an *OrderedCollection* are polymorphic. But *BusinessObjectList* also supports behavior that solves a client/server performance problem: in practice, a search may return so many objects that either the time to move all the data from server to client is unacceptably long or the objects consume too much of the client's memory. The search object therefore asks the server to limit the number of matching objects it returns, say to the first 50 business objects, and then creates a *BusinessObjectList* to hold these objects. If the user wants to see the next 50, the *BusinessObjectList* scrolls, which really means that it asks the search object to retrieve the next 50 matching business objects from the server. Thus a *BusinessObjectList* holds a limited number of the objects that match the search description, but it is smart enough to replenish itself with the others as needed. Because it is not the whole list but can access the whole list, we can call it a *virtual list* that must *mega-scroll* to reach all its business objects.

*What the programmer does.* He builds concrete subclasses of *Search* such as *LoanSearch*, and customizes *LoanSearch* to handle the search criteria that matter for loans.
The highlights of filtering or searching are thus:

<figure><img src="image_156.png" /></figure>

Note that a search object must collaborate with a broker to actually retrieve objects from the server. Also note that a **BusinessObjectList** must know the search object that produced its contents so that it can re-execute this search when it mega-scrolls.

## 19.5 Updating

An application that allows the user to update data at the server must support two basic scenarios:

1. The user makes changes and commits them,

2. The user makes changes, thinks better of them, and wants to discard them.

*What the framework does.* Because the user wants to be able to revert a business object to its original state, the framework must retain the object's original data somewhere. The *objects from records* pattern (page 220) that we are using for materialization provides storage for both the original data and the user's changes. The pattern accommodates a **Byte-Array** of data plus a cache of converted sub-objects. (The drawing on page 223 shows one implementation, with both the byte array and cache stored in the record object.)

The **ByteArray** houses the original data and the cache houses current objects, whether they are objects cached by conversions from the **ByteArray** or modifications to these objects made by the user. Only when the user commits the changes in the cache does the framework convert the cached objects to raw data in the **ByteArray** and send the data back to the server. If the user instead discards the changes, the framework simply empties the cache, which effectively presents the original **ByteArray** as the current data.
*What the programmer does.* This is another example of black-box reuse. Assuming that the user can click buttons for committing or reverting, the programmer writes code that responds to click events by invoking `Loan>>update` or `Loan>>revert`, respectively. These methods are actually inherited from `BusinessObject`, and so the framework does the rest.

Here are the highlights of the design for updating and reverting:

<figure><img src="image_157.png" /></figure>

In keeping with the model-view or observer pattern (page 228), the view's loan is represented here by an instance variable named `model`.

## 19.6 Summary

The programmer who uses a framework is in something of a straitjacket. He loses some of programming's traditional freedom of choice. Because of the Hollywood Principle, his first thought is not, "I'll begin by laying out some logic," but, "Where am I compelled to begin?"<fnref n="3" /> Since we are talking about object-oriented programming, he answers this question by looking for the framework's abstract classes and their subclassResponsibility methods.

<footnote n="3">³ The Hollywood Principle illustrates a programming trend: application programmers are writing more and more code that conforms to expectations or guidelines from elsewhere. Another example of this trend is the handlers you wrote in Chapter 12 to respond to events and callbacks. Yet another is the hook methods that are object-oriented counterparts of user exits in early mainframe systems programs (see the aside on page 66). Since you are not obliged to write handlers or hook methods, these represent a variation on the Hollywood Principle in which you don't have to be there when the call comes. On the other hand, subclassResponsibility methods are obligatory—you had better be there when the call comes or you will be in trouble.</footnote>
Object-oriented frameworks have other characteristics:

* A framework provides white-box reuse, as well as the more familiar black-box reuse you get from calling an API or using a library of container classes. A framework user must understand the abstract classes and what is expected of their subclassResponsibility methods, whereas a container user just calls encapsulated add: and remove: methods. White-box reuse follows from the Hollywood Principle: the framework will have expectations when it calls your code, and it is your job to look into the framework far enough to understand what those expectations are. They may be as straightforward as making sure you override a method named foobar, but whatever they are, you must understand them.

* Learning to use a framework takes effort. You can't do white-box reuse until you learn the abstract classes and their subclassResponsibility methods. Because the abstract classes interact with one another, you generally have to learn more than one class before you begin writing your application. Black-box reuse, on the other hand, usually occurs one class at a time. You are likely to use a Set today and a SortedCollection tomorrow; you don't have to understand interactions between them.

* Developing a framework takes time. You can't know a framework is reusable until you've used it on more than one project—that's the definition of reusability—so it takes at least twice as long to build a framework as to deliver a project. A framework gradually improves as it is refined on successive projects. The client/server framework outlined in this chapter has evolved over several years from really crude beginnings, and it continues to improve, with no end in sight.

* Developing a framework is hard. If it is going to simplify the application programmer's job, it must do all the things he doesn't want to do. For a client/server framework, these things can include conversions between databases and objects, communications and transaction management, event processing and window management, usability, and even performance optimizations. Technical difficulties that are not specifically part of the business problem are better left to a reusable framework than agonized over by each application programmer.

For background on the conceptual and practical considerations in client/server computing, see [Orfali et al. 1994]. The principles governing the client/server framework touched upon in this chapter are the subject of [Wolf and Liu 1995]. The actual framework is known as MFW (materialization framework). However, the ideas, names of classes and methods, and algorithms here are simplified for clarity and do not coincide literally with their counterparts in MFW, nor does this chapter cover the full scope of the framework.
Object-oriented frameworks can deal with any aspect of computing: *Common-Point* consists of myriad related C++ frameworks for dealing with problems ranging from graphics to document-editing to National Language Support to I/O device drivers [Lewis et al. 1995]. *Accounts* is a Smalltalk framework for building business applications that maintain general ledger accounts, inventories, investment accounts, and the like [Johnson 1995]. *MacApp* is a framework for producing applications having the Macintosh look and feel using either C++ or Object Pascal [Schmucker 1986; [Lewis et al. 1995]. And *MVC* is, as historians say about certain landmarks, the oldest continuously operating framework in the world.

## 19.7 Commentary: varieties of brokers

The number of kinds of brokers in the computing world is enormous. They are at the heart of every distributed computing architecture.

Brokers that operate with server programs and exchange standard information units—records, CORBA objects, Network OLE objects…—are known as transaction brokers. Transaction brokers are compatible with relational databases: if the server data are relational, the server programs convert the data to and from standard information units. Transaction brokers partition logic between computing nodes; distributed systems based on them therefore decouple clients from servers, which enhances a system’s long-term flexibility.

From the point of view of a client application, a broker object functions much like an object database: it retrieves objects, updates them, manages concurrent access to them, and so on. If you think of brokers and object databases interchangeably, then it is not hard to imagine object databases as an alternative approach to distributed objects. Thus you should expect object databases to compete with transaction brokers for dominance in client/server and distributed object computing.

Despite the benefits of transaction brokers, SQL brokers are more popular. They can produce working applications quickly because they don't require additional programs to be written in a foreign language at the server. On the other hand, they require a relational database at the server, and they couple the client tightly to the structure of the relational tables—the antithesis of the spirit of encapsulation. In the long run they will remain useful for proofs-of-concept and prototypes, but transaction brokers will displace them for extensible, high-performance applications.
## 19.8 Commentary: buying outdoes inheriting (sometimes)

framworks prove that there is an essential niche in the world for inheritance and white-box reuse. Moreover, we are all conditioned to savor the appeal of inheritance—creating a specialized object by inheriting from some class that provides function close to what we need. Inheritance is one of the most touted techniques in object-oriented programming and is so easy to do that we are liable to overdo it. Over time, however, good designs inherit less and buy more (Chapter 9). That is, we gradually realize ways to reduce white-box reuse in favor of black-box reuse.

Here is an example. A loan object's data are different from a customer object's, so the fields in their underlying records, as well as their sizes, are decidedly unlike. It is therefore tempting to create two subclasses of class Record, namely LoanRecord and CustomerRecord, each of which supports appropriate field-by-field accessors, such as atCollateral and atCollateralPut: for a LoanRecord, and atName and atNamePut: for a CustomerRecord.

This straightforward design works, but is unattractive. First, it proliferates classes, necessitating a separate record class for each class of business object. Second, the inheritance is not fundamentally behavioral; rather it is based on inert data attributes like the loan's collateral description and the customer's name. Interesting objects ought to be characterized more by behavior than data. In fact it seems here that each subclass is accompanied by an entire family of methods that have nothing in common with the rest. No methods are reused, shared, or overridden, and none are candidates for subclassResponsibility methods. The final and perhaps most alarming indication is that these record classes form an inheritance hierarchy with no polymorphism in sight.

These indications encourage us to consider an alternative, non-inheritance-based solution. We consider then a single concrete Record class and design it to be configurable so that its instances can serve either a loan or a customer. Although the records for loans and customers have disparate sizes and contents, we design them to be behaviorally identical. Specifically, their essential public selectors are at: and at:put:, where the first keyword parameter is the name of a field, such as #Collateral or #Name. In this way we rid the design of an entire hierarchy of record subclasses, trimming countless methods as well as classes from the application. This inheritance-free design agrees with the objects from records pattern (see the figure on page 223).
Here are two other examples of this progression away from inheritance-based designs:

* Pluggable views let programmers configure widgets instead of having to create subclasses of them (page 140).

* Early object-oriented exception-handling mechanisms laid out class hierarchies of exceptions, even though the essential behavior of all exception objects is the same. Hence recent exception schemes (including IBM Smalltalk's) use instance hierarchies of exceptions. This scheme nips in the bud a potential flurry of class building.

Let these arguments induce you to avoid inheritance at all costs, remember that inheritance designs remain desirable as long as you find polymorphism in them. Thus the shortcomings outlined above do not apply to the key abstract classes we visited in this chapter, such as `BusinessObject` and `Broker`. You will find lots of overridden methods and polymorphic behavior (methods `Broker->objectClass` and `Business-Object->identityKey`, for example) in the subclasses of these abstract classes, which should reassure you that this inheritance-based design is entirely appropriate and worthwhile.
## Metaclasses

We have now learned about polymorphism, patterns, frameworks, and the rest of the customary object-oriented topics. This brief chapter offers a respite from those mainstream topics and a final excursion for readers who are curious about just how far Smalltalk goes to celebrate its consistent view of objects. Along the way it answers a simple but perplexing question: "Where is method new?" It is possible to program competently in Smalltalk for years without understanding the answer, but the answer is an opportunity to discover the abstruse world of *metaclasses*.

### 20.1 Facts about metaclasses

We begin with a challenge: since a Smalltalk class is an object too, it must be an instance of something. What? Each class is an instance of its own *metaclass*. If you think of classes as factories, then you can think of metaclasses as the factories that produce ordinary factories like *String*, *Date*, *Stream*, and *Whale*.

Metaclasses have two unusual characteristics:

1. Every class is the only instance of its metaclass. In other words, each metaclass has exactly one instance, no more and no less, and that instance is an ordinary class.

2. Metaclasses have no names. This explains why you won't see them in any browsers. How then do you see them in Smalltalk? The same way you see the class of any object in Smalltalk—by sending the object the message *class* and displaying or inspecting the result. Thus, just as displaying `2.7182 class` produces *Float*, displaying *Whale class* produces the metaclass of *Whale*. But how would Smalltalk display this metaclass? After all, I have said that metaclasses have no names. The answer is barely satisfying: Smalltalk only displays *Whale class*. That is, Smalltalk
only parrots the original message. Disappointing or not, this is how Smalltalk informs us that the result of a message is a metaclass.

* Predict the result of displaying each of the following expressions. If you are uncertain, try the experiments.

```
'melatonin' class
String class
Penguin new class class
Bird class
Bird class allInstances size
```

**Solution:** Your answers should be *String*, *String class*, *Penguin class*, *Bird class*, and *1*.

Having come this far, you will naturally wonder, "Isn't a metaclass an object too? If so, musn't it also be an instance of something?" The answer is indeed yes, a metaclass is an object, and the something it is an instance of is a class whose name is *Metaclass*. In effect, *Metaclass* is the factory that produces *all* the metaclasses we have been talking about. *Metaclass* then must be quite large.

* How many instances of *Metaclass* are there?

**Solution:** The instances of *Metaclass* are the metaclass objects, and we know there is precisely one for each ordinary class. Therefore there are as many instances of *Metaclass* as there are ordinary classes in Smalltalk. In the version of VisualAge I am now using, that amounts to about 2100 instances. You can count the metaclasses in your own system by displaying *Metaclass allInstances size*.

Notice that *Metaclass* has a name. It is an ordinary class! Its instances just happen to be these peculiar objects known as metaclasses.

## 20.2 Inheritance

* Display the result of each of these expressions.

```
Integer superclass
Penguin superclass
Penguin new class superclass
Penguin class superclass
```

**Solution and discussion:** The first two responses are dull: *Number* and *Bird*. But the result of the last two messages is important news about the inheritance of metaclasses. The responses, *Bird* and *Bird class*, tell us that the superclass of *Penguin's* metaclass is *Bird's* metaclass. Invent and experiment with other examples involving classes and the
superclass message. Your experiments should confirm that whenever A is a subclass of B, A's metaclass is also a subclass of B's metaclass. More eloquently, *inheritance of metaclasses parallels inheritance of classes*.<fnref n="1" /> We mustn't forget this discovery, so let's give it a name, say, *Rule P* (for *Parallel*).

## 20.3 Method new

Since a class is an object, it has ordinary methods, just as other objects do. Ordinary methods would be called instance methods, but for classes we have been using a special name for their methods, namely *class methods*. Thus, "class method" is merely a convenient label for referring to an instance method of the class's metaclass. It is easier to talk about "a class method for *Whale*" than "an instance method for *Whale's* metaclass, *Whale class*."<fnref n="2" />

* Of all the class methods you will ever need, *new* is the most important. Suppose you write a class method *new* for *Bird*, and you don't write one for *Penguin*. What method do you expect the message *Penguin new* to execute? Why?

*Solution:* From our past experience, we expect the *new* method for class *Bird* to execute. That's because we believe that class methods are inherited. But now we have a reason for this inheritance: a class method is really a metaclass instance method, which like any instance method can be inherited from its superclass. But the superclass of *Penguin's* metaclass is *Bird's* metaclass (Rule P), so if *Penguin's* metaclass has no *new* method, it inherits the *new* method from *Bird's* metaclass.

This logic is pretty satisfying. Class methods are inherited because of Rule P. But here's the shocker. Suppose you don't write any *new* methods in the *Animal* hierarchy at all. What method do you expect the message *Penguin new* to execute? Everyone's first guess is a plausible one—the *new* class method in *Object*. But there is no such method! Class *Object* has no *new* method selector, either instance or class.

We will have to push a little further to find the default *new* method in *Smalltalk*.

<footnote n="1">¹ Or, the superclass of the metaclass is the metaclass of the superclass.</footnote>

<footnote n="2">² Similarly, since a class is an object, it has a right to its own instance variables. These instance variables have a special name too: they are known as *class instance variables*. Thus, "class instance variable" is the convenient label we use to refer to an ordinary instance variable of the metaclass. We needed class instance variables for the solitaire pattern on page 230.</footnote>
## 20.4 The full picture

We are going to assemble a schematic diagram that shows the conceptual relationships between instances and their classes and classes and their superclasses. You have seen the convention before, on page 17, but here it is again in a nutshell:

<figure><img src="image_158.png" /></figure>

The relationships between ordinary instances, their classes, and superclasses look like this:

<figure><img src="image_159.png" /></figure>

The parallel relationships for classes as objects, their classes, and superclasses look like this:

<figure><img src="image_160.png" /></figure>

Each metaclass has exactly one instance; these instances are classes and are shaded to distinguish them from ordinary instances. From bottom to top they are *Penguin*, *Bird*, *Animal*, and *Object*. Notice the appearance of a class named *Class* that conveniently contains all the class objects. The picture shows that every class is a *Class*, which is a reassuring but unremarkable fact.<fnref n="3" />

<footnote n="3">³ You encountered the class named *Class* in another context, while solving the exercise on object memory layouts on page 195.</footnote>
Finally, the metaclasses are objects in their own right, and they all reside in a class named *Metaclass*. You can think of the metaclass objects depicted from bottom to top as *Penguin class*, *Bird class*, *Animal class*, and *Object class*.

<figure><img src="image_161.png" /></figure>

And here is the result of assembling all these schematics into a whole:

<figure><img src="image_162.png" /></figure>

One of the side effects of this diagramming technique is that if all 2100 or so classes in VisualAge were represented in one diagram, each class would appear twice, once as a rectangle to indicate its subclass/superclass relationships and once as a shaded circle to indicate what it is an instance of. Similarly, every metaclass would appear twice, once as a rectangle and once as a striped circle.
Notice that one additional class has appeared—**Behavior**. **Behavior** is a superclass of both **Class** and **Metaclass**.<fnref n="4" /> As its name and position in the hierarchy suggest, it gathers all the behavior that we would expect for class-like objects.

**Behavior** is in fact the answer to the question that began this chapter: the default method **new** is an *instance method* in **Behavior**. A glance at the diagram shows that this is an excellent location for **new**. For if none of the animal metaclasses implements a **new** method, inheritance up the metaclass hierarchy in the center of the diagram shows that the lookup for the message **Penguin new** will eventually arrive at **Behavior**, where the default **new** will execute.

In addition to **new**, what other instance methods could plausibly reside in **Behavior**? Well, any method that makes sense for all the class-like objects. By browsing class **Behavior** you will find alluring methods like **allSubclasses**, **allSuperclasses**, **instVarNames**, **methodDictionary**, as well as ones you've already used like **new** and **allInstances**.

## 20.5 Recapitulation

Smalltalk is pure. "Everything is an object," and every object is an instance of some class. Even an object like a class or metaclass is an instance of some class. The diagram above records these instance-of relationships as circles within rectangles. Whether a circle represents an ordinary instance, a class as an instance, or a metaclass as an instance, it is still an instance of some class, represented by the rectangle enclosing it.

The diagram also records subclass relationships as nested rectangles. Any class-like object, whether a class or a metaclass, also occurs in the diagram as a rectangle. And its superclass occurs as the immediately surrounding rectangle.

The left and middle columns in the diagram illustrate Rule P, that metaclass inheritance *parallels* class inheritance—that the superclass of the metaclass is the metaclass of the superclass. A *class* message like **Penguin new** is really an *instance* message of the metaclass. In the absence of any overriding implementations of **new**, it executes the default *instance* method **new** found in class **Behavior** at the top of the metaclass hierarchy.

<footnote n="4">⁴ In IBM Smalltalk and VisualWorks have yet another class—**ClassDescription**, which is a subclass of **Behavior** and a superclass of both **Class** and **Metaclass**. Its purpose is administrative, and so it would add nothing to the present discussion.</footnote>
## 20.6 Exercises

It is a simple matter to verify any relationship in the diagram by experimenting with an appropriate message. For example, the diagram asserts that **Penguin's** metaclass is a subclass of **Bird's** metaclass. To verify an *inheritance* relationship like this, use the **superclass** message. Thus, you would *display* **Penguin class superclass** and expect a result of **Bird class**.

Similarly, to verify an *instance* relationship, such as the diagram's assertion that **Penguin's** metaclass is an instance of **class Metaclass**, use the **class** message. Thus, you would *display* **Penguin class class** and expect a result of **Metaclass**.

* Conversely, the diagram can help predict the result of the messages **class** or **super-class**. Use the diagram to predict the result of *displaying* each of the following messages. Of course you can also verify your answers by running the experiments:

```
Bird new class
Bird new class superclass
Bird class
Bird class superclass
Animal class superclass
Object class superclass
Bird class class
Animal class class
Object class class
Behavior class
```

* The diagram is incomplete. A large Smalltalk image contains hundreds of thousands of live objects instead of the 19 shown here. Where in the diagram would each of these objects, represented as plain, shaded, or striped circles, be?

* A whale instance

* A string instance

* **Whale**

* **String**

* **Whale's** metaclass

* **String's** metaclass

* **Metaclass**

* **Metaclass's** metaclass

You can verify your answers by experimenting with the objects above, starting by sending each of them the message **class**.
CHAPTER 21

Why developing software is still hard

The whole job of software development remains about as hard as ever. Every aspect is hard: making sense of requirements, designing good classes, building coherent user interfaces, writing extensible code. Objects add an exciting flavor to the enterprise, but object-oriented development efforts often don’t achieve their goals, and many end up as downright failures. What goes wrong?

21.1 Misconceptions

Object-oriented software development is not the bed of roses that many expect. This section challenges some of the popular misconceptions, and should adjust your expec- tations to a realistic level.

Object-oriented development is easier to learn and do

Reality: The Smalltalk language is easy to learn because it is so small. But the language by itself doesn’t do much. It is powerful only in conjunction with the hundreds of foundation classes and thousands of supporting classes that are part of today’s Small- talk products. You will have to learn many of these classes before you can write clean Smalltalk code. This takes time and practice.

It also takes time to become proficient in applying the ideas in this book—design- ing with containers, polymorphism, patterns, and so on. Everyone has the innate abil- ity to understand and talk about objects, but not everyone will work long and hard
enough with them to become a good designer. Look at it this way: object-oriented development increases our toolkit of techniques, which gives us more ways than ever to make a mess. Without the maturity that comes with experience, it is harder than ever to pinpoint desirable solutions in this enlarged universe of possibilities.

### Inexperienced programmers are better with objects

A popular misconception about object-oriented programming, particularly Smalltalk programming, is that it is detrimental to have had conventional programming experience, because bad habits acquired from this experience will have to be unlearned. The extreme form of this misconception is that it is better never to have programmed than to have been corrupted by conventional programming languages. Thus, the argument goes, an object-oriented project can succeed better with inexperienced programmers than it would with experienced ones.

*Reality.* The evidence suggests otherwise. Programming experience is advantageous for learning object-orientation.<fnref n="1" /> And projects that move ahead, meet their milestones, and satisfy users and managers, are staffed by knowledgeable programmers—the more expert, the better. Expert programmers excel at the whole infrastructure of software development—connectivity, databases, versioning and configuration management, testing, procedural logic, requirements gathering—all of which were essential to software development before objects were popularized and none of which have been obsolesced by objects. And expert programmers learn objects faster, appreciate their ramifications, and sense how to apply them to problems at hand.

### Object-oriented projects are more successful

*Reality.* An object-oriented project is no more likely to succeed than any other project. Out-of-touch leadership, misplaced optimism, complacency, the wrong tools, and all the rest are just as likely to afflict an object-oriented project as any other. Successful projects need business acumen coupled with technological knowhow, and you can find these qualities in conventional projects as well as in object-oriented ones.

### Object-oriented applications enjoy reuse

*Reality.* A project enjoys reuse if a coherent framework is in place. A framework's abstract classes help developers avoid redundancy. But frameworks are hard to build,

<footnote n="1">¹ See the study of several hundred students in [Liu et al. 1992].</footnote>
especially for the first problem that the framework is meant to address. Thus reuse within one project is not automatic.

Reuse of objects across projects is also not automatic. Plug-compatible objects are rare. Under the pressures of software development, it is hard enough to make an object work well for the product it is designed for, let alone for one it isn't designed for. The fellow who built the first fire didn't worry about building one in the rain until later. The first one demanded all his attention.

When reuse occurs across projects, it is commonly in the form of a framework that was successful on another project. A good framework's abstract classes stand a chance of being applicable to multiple projects. Eventually we will also succeed in assembling corporate or industry libraries of concrete classes, but only for problems that we understand thoroughly—old problems. New problems demand new solutions, for which there is nothing yet to be reused. Meanwhile, your most reusable asset is your design: code is less valuable than the thinking that went into its creation. Recast in the vocabulary of this book, an organization's real assets are the conceptual models of objects and patterns that its people hold. Therefore, for some time yet, the organization will be better off with the people than the code.

## Performance depends on the language

*Reality.* Performance is popularly ascribed to the programming language: assembler and C++ are fast; LISP and Smalltalk are slow. But the effect of programming languages on performance is smaller than the effect of design. A good Smalltalk design is faster than a bad C++ design, and vice versa. Design therefore matters more than the language.

Be especially wary of the performance of distributed objects. These are typically objects that are portable enough to operate in either a Smalltalk or a C++ environment. We measured the performance of one such object to be 70 times slower than its native Smalltalk counterpart. Extreme generality is almost always as costly as it is seductive.

## If it's demo-able, it's do-able

*Reality.* A demo is the tip of the iceberg. The hard, time-consuming work comes after, and under the demo, in producing robust, fast distributed or client/server support. Making objects persist across a network is tough. (See the border problem on page 267.)

Here's a rule of thumb: from the time the software operates fully, including accessing samples of actual data in a local database, allow half again as much effort to deliver the final product. In other words, a fully operational requirements release, which
appears to a user as the final product, consumes only 40 percent of the effort. It is
important to get this message across to everyone who is waiting for the final product,
or else you stand the risk of disappointing your sponsors. What they can touch and see
doesn't change for most of the development cycle.

GUI builders make it easy

*Reality:* GUI builders alleviate tedium. They are a pleasurable addition to our bag of software tools. But they don't make model-view separations automatic and they divert us from the profoundly challenging task—design. (Remember Chapter 13.)

*"I design in Smalltalk"*

*Reality:* Smalltalk programming is unusually close to design, but it is not the same as design. If you are working at a blackboard, whiteboard, with CRC cards, or somewhere else away from your computer, you are clearly designing. Good design is often a social activity. Very often, hard design problems succumb when you try to explain the difficulty to someone else, and some inconsequential remark triggers an idea that pays off.

Nevertheless, much of the time you spend in front of a Smalltalk system is honest
design time. Designing is weighing alternatives, including discovering them in the
first place and eventually rejecting all but one. This is what you are doing when you
investigate classes (remember that today's Smalltalks contain thousands), read and
experiment with their methods, or create your own throwaway classes and methods.
Struggling over naming classes and selectors, or wordsmithing comments, counts too.
Working in Smalltalk can be a form of design, but it is not the only form.

21.2 Where projects go awry: borders

Spectacular project overruns occur when development teams underestimate the diffi-
culty in connecting their applications to other critical computing systems. These sys-
tems may be off-the-shelf database products or homegrown systems that are de facto
standards for the business. Crossing the borders between the Smalltalk application and
each of these systems requires thoughtful design. Smalltalk objects are on one side of
each border, and something quite different is on the other. Development teams rarely
invest enough time or talent to resolve this mismatch.

The classic system border is the relational-to-object interface that occurs in most
of today's client/server applications. The database server may be on a local LAN, but
if it is at a remote or mainframe computer the number of conceivable techniques for crossing the border multiplies considerably. Culling the solutions that cannot handle the size or flux of traffic, or cost too much to implement, or are difficult to test, takes seasoned developers. Clean, efficient translations result from intimate familiarity with both sides of the border.

The hurdles proliferate when other kinds of “servers” enter the picture. The requirements of projects I’ve worked on include borders with other corporate systems—the payments system, the global customer database, the workflow system, and so on. These borders can be treacherous, for these reasons:

* The other system isn’t working yet.

* The other system was never designed to have an interface with our new client application.

* The interface exists, but new programs will have to be written on the other system to process our client’s requests.

* The system is written in another language, and so we must entrust the work to an entirely different organization.

* The physical connection to the other system is unreliable.

* The cost of testing the border crossing skyrockets.

A small failure at one of these system borders stops the application cold; this kind of failure is more critical and costly than a bug in a user interface or model object. Experienced project planners allot more than half (60 percent—see page 266) of a project’s resources to the border problem. Turnkey, black-box solutions rarely match your problem and are difficult to adapt. Workable solutions involve frameworks on one side and perhaps foreign languages on the other.

System borders may be the most spectacular failure points, but all borders are opportunities for missteps. Chapter 13 concerns the treacherous human-computer border. That border dovetails with what is traditionally called requirements gathering, which is the border between the problem-domain expert and the analyst. Ill-defined requirements acquired at this border are at the heart of many disappointing projects. But every human-to-human border in software development exacts some toll for the inefficiency of handing off ideas.

The ultimate, fine-grained border is the public interface of a programming object. Each object is supposed to have an understandable outside, consisting of its public method selectors, so that people will know how to use it. Getting these object borders right is the programmer’s core obligation. The lesson of individual objects coincides with the lesson of large-scale software development: borders, or interfaces, matter
most. Peter Deutsch, one of the eminences from Smalltalk's heyday at Xerox PARC, summarized it thus: "Interface design and functional factoring constitutes the key intellectual content of software and is far more difficult to recreate than code" [Deutsch 1991].

## 21.3 Characteristics of successful projects

If we are going to cross our borders efficiently, we will have to understand them. The first guideline is therefore readability.

### Readability

You sometimes encounter software in which, as soon as a bug appears and it becomes necessary to peer into the code, you discover a fragile labyrinth of object-oriented spaghetti. You have no hope of fixing the bug, let alone extending the software, without introducing new errors. Working software isn't impressive unless it is also a joy to read: it should hold no mysteries.

Readability plainly involves comments; style; names of methods, classes, and instance variables; and so on. (See [Skublics et al. 1996].) But it includes broader considerations, like window classes weighed down by too many methods, or complicated behavior that ought to have been reified, or code that could be re-factored into patterns or abstract classes, or.... Readability is almost synonymous with good design, and is more of an art than a measurable commodity.

Motivation to write clear code can come from unusual sources. One project, suffering in the wake of client/server code left behind by some eager but inexperienced framework developers, sponsored a contest for "The Method from Hell." To win, you had to find the most hopelessly incomprehensible method in the framework. As a by-product of this friendly competition, developers thought twice before writing methods of their own that might be eligible for future honors.

Reading samples of code is like taking someone's temperature: a project with muddy code, like a person with a fever, cannot be healthy. The code is where all other factors come together; if it is unreadable you have a problem somewhere. You may not know immediately if the root of the problem is faulty analysis, crude design, or slipshod implementation, or even haphazard organizational structures or processes. But you know you must begin the investigation.
## Names

Clear names are an essential element of readability: names of methods, names of instance variables, names of classes. The first thing a Smalltalk programmer does when looking at a class is browse through the class's method selectors. Well-named selectors are signposts; poorly named ones confuse programmers and hinder understanding. Bad names haunt a project forever; good names trumpet the software's design.

Names are especially significant in object-oriented software. The name someone gives a class is supposed to clearly and immediately evoke the nature of that class to everyone else—analysts, developers, testers. Effective names connote the right idea and act as handles for conversations between developers. Here are some examples of the consequences of names—a good, mediocre, and bad choice, respectively:

* Nicknames for ideas help developers communicate. After deciding to use **Skinny-Customer** for the name of a class of ghosts (page 226), we referred to instances as "skinnies." This nickname expedited countless rapid-fire conceptual discussions.<fnref n="2" />

* Precise names can be too cumbersome for day-to-day thinking and conversation. **MutualFundAccountTelephoneExchangeRole** may be precisely right, but it is a mouthful that takes a while for the brain to process. Sometimes it is worth sacrificing a little precision for the sake of a simpler name and to trust the context of a project to supplement everyone's understanding.

* At the other extreme, a name like **SmartGuy** is too vague. Explanations of this unfortunate name dragged on through weeks of meetings because it evoked disparate ideas in the minds of different people. Here, the choice of names impeded rather than enhanced design. (In this project, the behavior of **SmartGuy** encompassed ideas that could have been identified by several specific names, including **TaskMonitor** and **WorkflowServer**.)

Bad names waste time and money. We expend mental energy reconstructing what they mean. If a project names the yellow-rumped warbler a "red-winged blackbird," then whenever someone says "red-winged blackbird" we start to imagine a chunky dark bird in the reeds instead of the tiny flitty bird overhead that we are supposed to imagine. Our brains start down the wrong track, processing excess, irrelevant thoughts.

<footnote n="2">² We rejected several alternatives: **SummaryCustomer** (connotes collapsing and paraphrasing rather than simple subsetting); **LiteCustomer** (too trendy to stand the test of time); **DietCustomer** (pointlessly humorous); and **SynopsisCustomer** (difficult to repeat quickly during a spirited design conversation).</footnote>
## Understanding the problem

Nothing is more disgraceful than paying expensive Smalltalk programmers to produce what they think an organization needs. If they don't understand the problem they've been asked to solve, be it how bankers finance international trade or geneticists infer the locations of genes on chromosomes, the project's outlook is grim. The remedy, whether you call it requirements gathering or object-oriented analysis, is a sizable investment of time and work with someone who *does* understand the problem. The border between developers and users must be crossed.

## Understanding object-orientation

This is the obvious factor. Until you are comfortable with containers, abstract classes, polymorphism, and all the rest, your designs are bound to be crude. And until you have written a sizable body of Smalltalk code, you can benefit from an experienced Smalltalk programmer who reviews your work and suggests ways of cleaning it up.

## Leadership

Leaders may be managers, or team leaders, or programmers. The title matters less than the qualities. Effective leaders understand the problem and have firsthand experience with the power and limitations of their object-oriented tools. They also have political savvy: they are familiar enough with the surrounding organization to secure the support and resources the project needs. When any of these elements is missing, a project founders. It acquires the wrong tools and frameworks at the wrong times, and misapplies whatever it acquires. Something will work and delight the team or its customers, but no culture or discipline moves the effort toward an industrial-strength product. In the saddest scenarios, programmers and designers run amok formulating grand abstractions and trying to solve general problems. (If they knew the adage, "The devil is in the details," they would know that there are plenty of challenges in basic, concrete problems, and that until they overcome those challenges, any attempt to solve general problems is futile.)

I once heard it suggested that software development proceeds like the universe unfolding from the Big Bang. What happens at a key moment can shape the whole course of the future. The hiring of an unusual developer or manager, an insinuation about an architecture or tool, the fateful throwaway remark—any of these can lead eventually to products with entirely different looks and feels, performance, or durability. Each decision influences the next decision, and the next, and the next. Software development is a chaotic phenomenon like the weather, whose outcome in New York can
pivot on how a butterfly happened to flap its wings one month earlier in Beijing. No one is prescient enough to forecast the precise shape of the future. We only hope that our leaders' hunches—their flapping wings—will save us from the costliest blunders.

### Involving prospective users, continuously

*A parable.* A partnership was formed late in the 1980s to build a 14-mile road. The partners planned to reap a profit by charging motorists $1.75 for driving on it. The road would serve a high-income area with a rapidly growing population. In 1995 the road opened, toll booths and all. But the partnership landed immediately in financial trouble because few motorists were willing to pay $1.75 for the privilege of using the road. It turns out that no one ever asked any motorists how much such a road would be worth to them.<fnref n="3" />

Had this been a software project, the developers might have surveyed prospective users before the project began, and several more times while construction proceeded. As often as practical, the developers would even show the users what they hoped to deliver. This is the best way to prevent unwelcome surprises at the end of the project. The developers might even have decided that the project wasn't worth doing.

### Humility

Unless you've done it before, whether it's delivering industrial-strength software or running a marathon, it's going to hurt more than you think. Make the first milestone modest. You will learn object-oriented design and programming, how to make objects persist in a database across a network, and how to tune the application so that it performs acceptably.

## 21.4 An optimistic conclusion

You know by now that the overall difficulty of software development has not changed much from the days before objects. Design, leadership, technology, and so on were important then too. Producing high-quality software has always been difficult, and always will be difficult. Better tools and technologies help, but mostly to simplify the tasks that we have come to understand well enough to build tools for. The hard work is understanding new kinds of problems and designing solutions for them. No matter how good our tools get, the next generation of problems will tax our ingenuity.

<footnote n="3">³ You can find this story documented in the *Washington Post*, December 26, 1995.</footnote>
Objects present the opportunity for creating elegant software solutions by applying polymorphism and patterns and frameworks and the like. But amid the hoopla over these buzzwords we should not overlook the underlying benefit of objects. It is what we began with (page 7): objects equip programmers with the same cognitive tools, the same mental processes and metaphors, which the rest of the human population enjoys. Objects therefore reduce the cost of translating ideas from one mind to another. They reduce the occasions for misunderstanding throughout the software enterprise, from requirements analysis through final testing.

We don't know how to quantify the price of these misunderstandings, or the savings from preventing them. Misunderstandings are not as measurable as methodologies, tools, and schedules, or method size, numbers of abstract classes, depths of inheritance hierarchies, or numbers of patterns. We therefore scarcely appreciate the essential economic value of objects: they reduce misunderstandings, so that we can deliver better software.
## Some differences between dialects

The table below outlines some of the differences among major Smalltalk dialects. It is neither detailed nor complete and therefore is not meant for the faint of heart. But for readers with an investigative bent it hints at discrepancies that are likely to arise between this book, written for IBM Smalltalk, and other dialects. It also points to a few areas not discussed in this book where the dialects are based on fundamentally different precepts. Note that ParcPlace-Digitalk is working to converge the VisualSmalltalk and Visual-Works products into one offering, which will reconcile the differences between the last two columns in the table.

<table><thead><tr><th></th><th>VisualAge<br>(IBM Smalltalk)</th><th>VisualSmalltalk<br>(Smalltalk/V)</th><th>VisualWorks<br>(Smalltalk-80)</th></tr></thead><tbody><tr><td rowspan="3">Image name<br>(default)</td><td>image</td><td>v.exe<br>v.image (Macintosh)</td><td>visual.im</td></tr><tr><td>Execute</td><td>Do It</td><td>do it</td></tr><tr><td>Display</td><td>Show It</td><td>print it</td></tr><tr><td>Transcript's<br>class</td><td>EtTranscript</td><td>TextWindow</td><td>TextCollector</td></tr><tr><td>Global variables<br>(use sparingly)</td><td>Must be<br>explicitly declared</td><td>Prompts you on first<br>attempt to use one</td><td>Prompts you on first<br>attempt to use one</td></tr><tr><td>Class instance<br>variables</td><td>Yes</td><td>Yes—literally instance<br>variables of the class's class<br>(absent in older versions)</td><td>Yes—literally instance<br>variables of the class's class</td></tr><tr><td>Dispatching the<br>message aMsg</td><td>aMsg sendTo: anObject</td><td>aMsg perform</td><td>anObject perform: aMsg<br>selector with Arguments:<br>aMsg arguments</td></tr></tbody></table>
<table><thead><tr><th></th><th>VisualAge<br>(IBM Smalltalk)</th><th>VisualSmalltalk<br>(Smalltalk/V)</th><th>VisualWorks<br>(Smalltalk-80)</th></tr></thead><tbody><tr><td>Pure virtual (abstract,<br>deferred) method</td><td>subclassResponsibility</td><td>implementedBySubclass</td><td>subclassResponsibility</td></tr><tr><td>Opening a text<br>window</td><td>EtWorkspace new<br>show: 'Hello, world'</td><td>TextWindow new<br>openOn: 'Hello, world'</td><td>ComposedTextView<br>open: 'Hello, world'<br>asComposedText</td></tr><tr><td>Collection hierarchy<br>is subtyped</td><td>No</td><td>No</td><td>No</td></tr><tr><td>Finalization and<br>weak references</td><td>Yes</td><td>Yes (absent in<br>older versions)</td><td>Yes</td></tr><tr><td>Look and feel gov-<br>erned by platform's<br>window manager</td><td>Yes</td><td>Yes</td><td>No</td></tr><tr><td>Literal strings may<br>be modified</td><td>No</td><td>Yes</td><td>Yes</td></tr><tr><td>Literal arrays may<br>be modified</td><td>No</td><td>Yes</td><td>Yes</td></tr><tr><td>Block temporary<br>variables [bx] ...</td><td>Yes</td><td>No</td><td>Yes</td></tr><tr><td>Pool dictionary class</td><td>EsPoolDictionary</td><td>Dictionary</td><td>Dictionary</td></tr><tr><td>Pool dictionary keys</td><td>String</td><td>String</td><td>Symbol</td></tr><tr><td>Subclasses inherit<br>pool dictionaries</td><td>Yes</td><td>No</td><td>Yes</td></tr><tr><td>SmallInteger range<br>(on 32-bit platforms)</td><td>-2<sup>30</sup> to 2<sup>30</sup>-1</td><td>-2<sup>30</sup> to 2<sup>30</sup>-1</td><td>-2<sup>29</sup> to 2<sup>29</sup>-1</td></tr><tr><td>Broadcaster</td><td>AbtObservableObject<sup>a</sup></td><td>EventManager<sup>b</sup></td><td>Model<sup>c</sup></td></tr><tr><td>Exceptions</td><td>Instance hierarchy</td><td>Class hierarchy</td><td>Instance hierarchy</td></tr></tbody></table>

<sup>a</sup> Also, the same protocol, but less efficient and less encapsulated, is available for any Object. A third protocol is the traditional one using the class variable *Dependents* in Object.

<sup>b</sup> Also, the same protocol, but less efficient and less encapsulated, is available for any Object. Older versions supported the traditional protocol using the class variable *Dependents* in Object.

<sup>c</sup> This class supports the traditional (original MVC) protocol. Also, the same protocol, but less efficient and using the class variable *Dependents*, is available for any Object. ParcPlace-Digitalk intends to add EventManager broadcasting, as in VisualSmalltalk.
References

[Agha et al. 1989] Gul Agha, Peter Wegner, Akinori Yonezawa, editors. *ACM SIGPLAN Notices* (Proceedings of the ACM SIGPLAN Workshop on Object-Based Concurrent Programming, September 26–27, 1988), vol. 24, no. 4 (April 1989).

[Agha et al. 1991] Gul Agha, Carl Hewitt, Peter Wegner, Akinori Yonezawa, editors. *ACM OOPS Messenger* (Proceedings of the ECOOP-OOPSLA Workshop on Object-Based Concurrent Programming, October 21–22, 1990), vol. 2, no. 2 (April 1991).

[Alexander 1979] Christopher Alexander. *The Timeless Way of Building*. New York: Oxford University Press, 1979. The first of Alexander's twelve volumes (eight published, four to appear) discusses the "quality without a name."

[Alexander et al. 1977] Christopher Alexander, Sara Ishikawa, Murray Silverstein, with Max Jacobson, Ingrid Fiksdahl-King, Shlomo Angel. *A Pattern Language*. New York: Oxford University Press, 1977. The highly readable catalog of 253 patterns for building living spaces.

[America 1991] Pierre America. "Designing an Object-Oriented Programming Language with Behavioural Subtyping," *Foundations of Object-Oriented Languages: REX School/Workshop, Noordwijkerhout, The Netherlands, May 28-June 1, 1990, Proceedings*. Berlin: Springer-Verlag, 1991, pp. 60-90.

[Aristotle 330BC] Aristotle. "Parts of Animals," *A New Aristotle Reader*. J. L. Ackrill, editor. Princeton: Princeton University Press, 1987.

[Baker 1978] Henry G. Baker, Jr. "List Processing in Real time on a Serial Computer," *Communications of the ACM*, vol. 21, no. 4 (April 1978), pp. 280-294. Baker credits the idea of semi-spaces all the way back to work by Marvin Minsky in 1963; this paper hones the algorithm for real-time applications.

[Beck and Cunningham 1989] Kent Beck, Ward Cunningham, "A Laboratory for Teaching Object-Oriented Thinking," *ACM SIGPLAN Notices* (OOPSLA '89 Conference Proceedings), vol. 24, no. 10 (October 1989), pp. 1-6. The article that introduced CRC cards.

[Black et al. 1986] Andrew Black, Norman Hutchinson, Eric Jul, Henry Levy. "Object Structure in the Emerald System," *ACM SIGPLAN Notices* (OOPSLA '86 Conference Proceedings) vol. 21, no. 11 (November 1986), pp. 78-86.

[Booch 1994] Grady Booch. *Object Oriented Analysis and Design with Applications, 2nd ed.* Redwood City, CA: Benjamin/Cummings, 1994. Probably the most popular object-oriented design methodology.
[Briot 1992] Jean-Pierre Briot. *Tutorial 5: Object-Oriented Concurrent Programming*, OOPSLA '92. Ottawa, Canada, 1992.

[Buhr and Casselman 1992] Raymond J. A. Buhr, Ronald S. Casselman. "Architectures with Pictures," *ACM SIGPLAN Notices* (OOPSLA '92 Conference Proceedings), vol. 27, no. 10 (October 1992), pp. 466-483.

[CACM 1993] *Communications of the ACM* (Special Issue: Concurrent Object-Oriented Programming), vol. 36, no. 9 (September 1993).

[Cardelli et al. 1992] Luca Cardelli, James Donahue, Lucille Glassman, Mick Jordan, Bill Kalsow, Greg Nelson. "Modula-3 Language Definition," *ACM SIGPLAN Notices*, vol. 27, no. 8 (August 1992), pp. 15-42.

[Chambers 1989] Craig Chambers, David Ungar, Elgin Lee. "An Efficient Implementation of SELF, a Dynamically Typed Object-Oriented Language Based on Prototypes," *ACM SIGPLAN Notices* (OOPSLA '89 Conference Proceedings), vol. 24, no. 10 (October 1989), pp. 49-70.

[de Champeaux et al. 1993] Dennis de Champeaux, Douglas Lea, Penelope Faure. *Object-Oriented System Development*. Reading, MA: Addison-Wesley, 1993.

[Civello 1993] Franco Civello. "Roles for composite objects in object-oriented analysis and design," *ACM SIGPLAN Notices* (OOPSLA 1993 Conference Proceedings), vol. 28, no. 10 (October 1993), pp. 376-393.

[Coad 1992] Peter Coad. "Object-oriented patterns," *Communications of the ACM*, vol. 35, no. 9 (September 1992), pp. 152-159.

[Coad et al. 1995] Peter Coad, David North, Mark Mayfield. *Object Models: Strategies, Patterns, and Applications*. Englewood Cliffs, NJ: Prentice-Hall, 1995.

[Coad and Yourdon 1991] Peter Coad, Edward Yourdon. *Object-Oriented Analysis*, 2nd ed. Englewood Cliffs, NJ: Prentice-Hall, 1991.

[Collins 1995] Dave Collins. *Designing Object-Oriented User Interfaces*. Redwood City, CA: Benjamin/Cummings, 1995. The broadest and deepest resource relating user interfaces to object-oriented programming.

[Cook 1989] W. R. Cook. "A Proposal for Making Eiffel Type-safe," *ECOOP '89* (Proceedings of the 1989 European Conference on Object-Oriented Programming). Cambridge, UK: Cambridge University Press, 1989, pp. 57-70. Part of the subtyping debate; this paper supports contravariance of argument types.

[Cook 1992] William Cook. "Interfaces and Specifications for the Smalltalk-80 Collection Classes," *ACM SIGPLAN Notices* (OOPSLA '92 Conference Proceedings), vol. 27, no. 10 (October 1992), pp. 1-15. The definitive analysis of types versus classes in Smalltalk-80's collection classes.

[Coplien and Schmidt 1995] James Coplien, Doug Schmidt, editors. *Pattern Languages of Program Design*. Reading, MA: Addison-Wesley, 1995.

[Crick 1988] Francis Crick. *What Mad Pursuit: A Personal View of Scientific Discovery*. New York: Basic Books, 1988.

[Cunningham and Beck 1986] Ward Cunningham, Kent Beck. "A Diagram for Object-Oriented Programs," *ACM SIGPLAN Notices* (OOPSLA '86 Conference Proceedings), vol. 21, no. 11 (November 1986), pp. 361-367.
[Davis and Morgan 1993] John Davis, Tom Morgan. "Object-Oriented Development at Brooklyn Union Gas," *IEEE Software*, vol. 10, no. 1 (January 1993). Describes an early object-oriented tour de force.

[Deutsch 1991] L. Peter Deutsch. "Objects: Just Another Technology?" Presentation at *Symposium on Object-Oriented Computing*. Thornwood, NY: IBM, 1991.

[Dijkstra et al. 1989] Edsger Dijkstra. "On the Cruelty of Really Teaching Computing Science," *Communications of the ACM*, vol. 32, no. 12 (December 1989), pp. 1398-1404. Rejoinders follow by David Parnas, W. L. Scherlis, M. H. van Emden, Jacques Cohen, R. W. Hamming, Richard Karp, Terry Winograd, pp. 1405-1414.

[Eggenschwiler and Gamma 1992] Thomas Eggenschwiler, Erich Gamma. "ET++ Swaps Manager: Using Object Technology in the Financial Engineering Domain," *ACM SIGPLAN Notices* (OOPSLA '92 Conference Proceedings), vol. 27, no. 10 (October 1992), pp. 166-177. Terse descriptions of some patterns that have since entered the object-oriented vernacular.

[Feynman 1967] Richard Feynman. *The Character of Physical Law*. Cambridge, MA: MIT Press, 1967. Illuminating lectures aimed at the non-specialist.

[Gabriel 1993-1994] Richard Gabriel. (5 articles) "The quality without a name"; "Pattern languages"; "The failure of pattern languages"; "The bead game, rugs, and beauty, parts I and II"; *Journal of Object-Oriented Programming*, vol. 6, no. 5 (September 1993), pp. 86-89; vol. 6, no. 8 (January 1994), pp. 72-75; vol. 6, no. 9 (February 1994), pp. 84-88; vol. 7, no. 3 (June 1994), pp. 74-78; vol. 7, no. 5 (September 1994), pp. 44-49. A retelling of the architectural odyssey of Christopher Alexander, with attempts to link it to software.

[Gamma et al. 1995] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. *Design Patterns: Elements of Reusable Object-Oriented Software*. Reading, MA: Addison-Wesley, 1995. The standard reference on patterns, written by the so-called Gang of Four.

[Gibson 1990] Elizabeth L. Gibson. "Objects—Born and Bred," *BYTE Magazine* (October 1990), pp. 245-254. The first description of the Object Behavior Analysis (OBA) design methodology.

[Goldberg and Robson 1983] Adele Goldberg, David Robson. *Smalltalk-80: The Language and its Implementation*. Reading, MA: Addison-Wesley, 1983 (Reprinted with corrections, July 1985). The classic Smalltalk sourcebook, now, sadly, out of print.

[Hadamard 1954] Jacques Hadamard. *An Essay on the Psychology of Invention in the Mathematical Field*. Reprint of 1949 Princeton University Press edition, New York: Dover, 1954.

[IBM 1995] IBM Smalltalk Programmer's Reference: Version 3, Release 0. SC34-4493-02. IBM Corporation, 1995. Clear exposition of Motif widget support, as well as other facets of IBM Smalltalk.

[Ingalls 1986] Daniel H. H. Ingalls. "A Simple Technique for Handling Multiple Polymorphism." *ACM SIGPLAN Notices* (OOPSLA '86 Conference Proceedings) vol. 21, no. 11 (November 1986), pp. 347-349. The original discussion of double dispatch, succinct and lucid.

[Jacobson 1987] Ivar Jacobson. "Object Oriented Development in an Industrial Environment," *ACM SIGPLAN Notices* (OOPSLA '87 Conference Proceedings), vol. 22, no. 12 (December 1987), pp. 183-191.

[Jacobson et al. 1992] Ivar Jacobson, Magnus Christerson, Patrik Jonsson, Gunnar Overgaard. *Object-Oriented Software Engineering: A Use Case Driven Approach*. Reading, MA: Addison-Wesley, 1992.
[Johnson 1992] Ralph E. Johnson. "Documenting Frameworks Using Patterns," *ACM SIGPLAN Notices* (OOPSLA '92 Conference Proceedings), vol. 27, no. 10 (October 1992), pp. 63-76. Patterns for understanding the HotDraw framework.

[Johnson 1995] Ralph E. Johnson. "Accounts: A framework for business transaction processing," http://st-www.cs.uiuc.edu/users/johnson/Accounts.html.

[Johnson and Russo 1991] Ralph E. Johnson and Vincent F. Russo. "Reusing Object-Oriented Designs," *University of Illinois Technical Report UIUCDCS 91-1696*.

[Kay 1988] Alan Kay. Presentation at IBM symposium, *Directions in Object-Oriented Computing*. Thornwood, NY: IBM, 1988.

[Kay 1990] Alan Kay. "User Interface: A Personal View," *The Art of Human-Computer Interface Design*. Brenda Laurel, editor. Reading, MA: Addison-Wesley, 1990, pp. 191-207.

[Kay 1993] Alan Kay. "The Early History of Smalltalk," *ACM SIGPLAN Notices (History of Programming Languages-II)* vol. 28, no. 3 (March 1993), pp. 69-95. The lore of how Smalltalk came to be, told by its creator.

[Krasner 1984] Glenn Krasner, editor. *Smalltalk-80: Bits of history, words of advice*. Reading, MA: Addison-Wesley, 1984.

[Lakoff and Johnson 1980] George Lakoff, Mark Johnson. *Metaphors We Live By*. Chicago: University of Chicago Press, 1980.

[Lalonde et al. 1986] Wilf Lalonde, Dave Thomas, John Pugh. "An Exemplar-Based Smalltalk," *SIGPLAN Notices* (OOPSLA '86 Conference Proceedings) vol. 21, no. 11 (November 1986), pp. 322-340. An early attempt to resolve the type versus class conflict in Smalltalk.

[Laurel 1990] Brenda Laurel, editor. *The Art of Human-Computer Interface Design*. Reading, MA: Addison-Wesley, 1990.

[Lea 1992] Doug Lea. "Run-Time Type Information and Class Design," *USENIX C++ Technical Conference Proceedings 1992*. Usenix Association, 1992, pp. 341-347. Practical advice for using the recent RTTI feature of C++.

[Lewis et al. 1995] Ted Lewis, Glenn Andert, Paul Calder, Erich Gamma, Wolfgang Pree, Larry Rosenberg, Kurt Schmucker, André Weinand, John M. Vlissides. *Object-Oriented Application Frameworks*. Greenwich, CT: Manning Publications, 1995. Summaries of several notable frameworks.

[Lieberman 1986] Henry Lieberman. "Using Prototypical Objects to Implement Shared Behavior in Object Oriented Systems," *SIGPLAN Notices* (OOPSLA '86 Conference Proceedings), vol. 21, no. 11 (November 1986), pp. 214-223.

[Lieberman and Hewitt 1983] Henry Lieberman, Carl Hewitt. "A Real-Time Garbage Collector Based on the Lifetimes of Objects," *Communications of the ACM*, vol. 26, no. 6 (June 1983), pp. 419-429.

[Linnaeus 1753] Carl Linnaeus. *Species Plantarum, A Facsimile of the first edition 1753, with an introduction by W. T. Stearn*. London: the Ray Society, 1957 (vol. 1) 1959 (vol. 2).

[Meyer 1988] Bertrand Meyer. *Object-Oriented Software Construction*. Hertfordshire, UK: Prentice Hall International, 1988.

[Meyer 1992] Bertrand Meyer. *Eiffel: The Language*. Hertfordshire, UK: Prentice-Hall International, 1992.
[Muir ca. 1880] John Muir. *The Wilderness World of John Muir*. Edwin Way Teale, editor. Boston: Houghton Mifflin, 1954. The passage on page 147 comes at the climax of the adventure of the singular mutt Stickeen.

[Nelson 1990] Theodor Holm Nelson. "The Right Way to Think About Software Design," *The Art of Human-Computer Interface Design*. Brenda Laurel, editor. Reading, MA: Addison-Wesley, 1990, pp. 235-244.

[Objectshare 1995] WindowBuilder Pro 3.0 Tutorial and Reference Guide. Edition for IBM Smalltalk and VisualAge. Objectshare Systems, Inc., 1995. Includes excellent discussion of Motif widget programming.

[Orfali et al. 1994] Robert Orfali, Dan Harkey, Jeri Edwards. *Essential Client/Server Survival Guide*. New York: John Wiley & Sons, 1994. A comparative approach to the concepts and implementation alternatives of client/server computing.

[Petroski 1985] Henry Petroski. *To Engineer Is Human: The Role of Failure in Successful Design*. New York: St. Martin's Press, 1985. Failure has always been intertwined with progress, and always will be.

[Pirsig 1974] Robert Pirsig. *Zen and the Art of Motorcycle Maintenance*. New York: Bantam, 1974. A study of quality and the hopelessness of describing it.

[Plato 375BC] Plato. *The Republic*. London, UK: Penguin rev. ed., 1987. The date is approximate; the famous dialogue on beds begins Book X.

[Power 1988] Leigh Power. "Specification and Design of Objects," *ACM SIGPLAN Notices* (OOPSLA '87 Addendum to the Proceedings), vol. 23, no. 5 (May 1988), pp. 7-16. Kent Beck discusses a tiny pattern language for user interfaces that is as relevant today as then.

[Reenskaug 1996] Trygve Reenskaug, with Per Wold, Odd Arild Lehne. *Working with Objects: The OOram Software Engineering Method*. Greenwich, CT: Manning Publications, 1996. Peppered with wisdom on the human role.

[Rubin and Goldberg 1992] Kenneth S. Rubin, Adele Goldberg. "Object Behavior Analysis," *Communications of the ACM*, vol. 35, no. 9 (September 1992), pp. 48-62.

[Rumbaugh et al. 1991] James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy, William Lorensen. *Object-Oriented Modeling and Design*. Englewood Cliffs, NJ: Prentice-Hall, 1991. A standard reference on object design, slanted toward entity-relationship modeling.

[Sacks 1985] Oliver Sacks. *The Man Who Mistook His Wife for a Hat, and Other Clinical Tales*. HarperCollins, 1985. Revealing tales of neurological irregularities.

[Sakkinen 1989] M. Sakkinen. "Disciplined Inheritance," *ECOOP '89 (Proceedings of the 1989 European Conference on Object-Oriented Programming)*. Cambridge, UK: Cambridge University Press, 1989, pp. 39-56.

[Samples et al. 1986] A. Dain Samples, David Ungar, Paul Hilfinger. "SOAR: Smalltalk Without Bytecodes," *ACM SIGPLAN Notices* (OOPSLA '86 Conference Proceedings), vol. 21, no. 11 (November 1986), pp. 107-118.

[Sarkela 1989] John Sarkela. Presentation at IBM workshop, *Management Implications of Object-Oriented Programming*. Westlake, TX: IBM, ca. 1989.

[Schmucker 1986] Kurt J. Schmucker. *Object-Oriented Programming for the Macintosh*. Hasbrouck Heights, NJ: Hayden, 1986. The MacApp framework, plus an appendix on Macintosh UI standards.