```kotlin
collection := OrderedCollection new
    add: objectOne;
    add: objectTwo;
    yourself.
```

The last example shows the use of the message `yourself`, which always returns the receiver. The use of `yourself` can make code a lot more robust. For example, both lines below should give you an employee object. However, the first line relies on the `salary`: accessor conforming to standards and returning `self`. The second line ensures that you always get the correct result.

```kotlin
employee := Employee new salary: aSalary.
employee := Employee new salary: aSalary; yourself.
```

## Incorrect messages to Booleans

You send `ifTrue:`, `ifFalse:`, `ifTrue`: `ifFalse:`, and `ifFalse`: `ifTrue:` to the Booleans `true` and `false`. These values may be the result of evaluating an expression in parentheses. On the other hand, you send `whileTrue`, `whileFalse:`, `whileTrue:`, and `whileFalse:`, to instances of BlockClosure. Ie, the `if` messages are sent to a Boolean and `while` messages are sent to a BlockClosure. For example,

```kotlin
(some condition) ifTrue: [some code]..
(another condition)
    ifFalse: [this code]
    ifTrue: [that code].

[some code] whileTrue.
[some code] whileFalse: [more code].
```

## Not reinitializing class variables

A common error when using class variables to contain static information is to modify the information, but not reinitialize the variable. Class side `initialize` methods are invoked when code is filed into the image, but once the code is in the image, the `initialize` method is not automatically sent again.

A common partial solution is to have a comment saying `self initialize` at the start of the `initialize` method, which you select and execute after accepting the modified method. For example,

```kotlin
MyClass class>>initialize
    "self initialize"
    Messages := Dictionary new.
    Messages at: #notFound put: 'Not found'.
```

## Problems with copies

When you copy an object, the `copy` method does a *shallow* copy, which is a one-level-deep copy. The original object is copied, but no instance variables are copied — ie, the two objects have the same instance variable objects. Because of this, we have to be very careful what we do with copies. Let's look at examples of modifying a copied collection and a copied non-collection object. In the examples below, we'll use a `Person` class, with the instance variables `name` and `phone`, and accessors for both variables.
## Modifying copy of non-collection object

Suppose you make a copy of an Employee object for safe keeping while you modify the original. If you do the following, you'll see that personTwo now has a phone number of '444-5555', which is not what you wanted.

```groovy
personOne := Person new name: 'Alec'; phone: '555-5555'; yourself.
personTwo := personOne copy.
personOne phone replaceFrom: 1 to: 3 with: '444'.
personTwo inspect.
```

Now the chances are that you would not be replacing characters in a string, but rather the whole string, in which case there would be no problem. However, a Person object might contain an Address object. If you replaced the street address in personOne's address, you'd find this change reflected in personTwo. To overcome this problem, Person needs to implement postCopy. For more information, see Chapter 25, Hooks into the System.

## Modifying copy of collection

Let's create a collection of Person objects then copy the collection. We might expect that the Person objects in the second collection are copies of the Person objects in the first collection. However, this is not the case. Even though we copied the collection, the objects in the copied collection are the *same* objects as the objects in the original collection. In this example, we modify the phone number of one person. If we inspect the copied collection, we'll see that the person has the new phone number, '222-2222'.

```groovy
personOne := Person new name: 'Alec'; phone: '555-5555'; yourself.
personTwo := Person new name: 'Dave'; phone: '111-1111'; yourself.
collectionOne := OrderedCollection new add: personOne; add:
personTwo; yourself.
collectionTwo := collectionOne copy.
personOne phone: '222-2222'.
personTwo inspect.
```

If we create the second collection by copying the Person objects, we solve this problem. For example, if we create collectionTwo by doing the following, then inspect collectionTwo, the phone number will still be '111-1111'.

```groovy
collectionTwo := collectionOne collect: [:each | each copy].
```

If you have an object that contains a collection in an instance variable, there's a question of whether you should even give access to the collection. For more information, see the section on Accessors for Collections in Chapter 4, Variables.

## ^ in block returns from method

There is unfortunately no way to return from a block other than hitting the right square bracket. If you use a caret (^) to return, you will exit the method as well as the block. For example, the following will exit the method.

```groovy
MyClass>>myMethod
someCondition ifTrue:
    [self someCode.
anotherCondition ifFalse: [^false].
```
```java
self moreCode.
self otherCode].
```

For the code to work correctly, you'll have to structure the code so that the right end of the block is hit. The first example keeps the code in the original method. The second example shows how you might put the block code in a different method to keep the methods simple and easy to understand.

```java
MyClass>>myMethod
  someCondition ifTrue:
    [self someCode.
    anotherCondition ifTrue:
      [self moreCode.
      self otherCode]].

MyClass>>myMethod
  someCondition ifTrue:
    [self someCode.
    self checkConditionAndDoStuff].
```

## Modifying a literal array

Modifying a literal array leads to unexpected behavior. For example, create a class `MyClass` and add the following method (the code can be found in the file `literal.st`).

```java
MyClass>>methodOne
| literalArray |
literalArray := # (1 2 3 4 5).
Transcript cr; show: literalArray printString.
(literalArray at: 3) == 3
  ifTrue: [literalArray at: 3 put: 99]
  ifFalse: [Transcript cr; show: 'On no. It is already 99']
```

The first time you evaluate `MyClass new methodOne` you will see the following.

```
#(1 2 3 4 5)
```

If you then evaluate the same line again, you will see this instead.

```
#(1 2 99 4 5)
On no. It is already 99
```

Looking at the method, it appears that you are assigning `#(1 2 3 4 5)` each time you execute the method. However, if you hold down the Shift key when selecting the method, you will see that the assignment line looks like the following.

```java
MyClass>>methodOne
| t1 |
t1 := # (1 2 99 4 5).
```

In other words, the literal array has been modified in memory. Let's look at another example, this time using a `WriteStream`. We use the `with:` message to position the stream pointer to the end of the collection.

```java
MyClass>>methodTwo
| stream |
stream := WriteStream with: # (1 2 3 4 5).
```
Transcript cr; show: stream contents printString.
stream nextPutAll: #(6 7 8 9).
Transcript cr; show: stream contents printString

The first time we execute `methodTwo`, the Transcript shows:

#(1 2 3 4 5)
#(1 2 3 4 5 6 7 8 9)

The second time we execute the method, the Transcript shows the following.

#(1 2 3 4 5 6 7 8 9 nil nil)
#(1 2 3 4 5 6 7 8 9 nil nil 6 7 8 9)

Again, the literal array has been modified in memory. This time it has actually grown rather than just having element values changed. As before, you can hold the Shift key down while selecting `methodTwo` in the Browser, and you'll see that the literal array is not what you thought it was.

How do we prevent this problem? The best way is to never do things directly with a literal array in your code. Always do things with a *copy* of the literal array. In the above two examples, if we had written the lines as below, there would be no problem.

literalArray := #(1 2 3 4 5) copy.
stream := WriteStream with: #(1 2 3 4 5) copy.

So, for example, if you have a method that returns a literal string, have it instead return a copy of the string, as shown below.

MyClass>>localName
^'Request' copy
23

Model-View-Controller

The Model-View-Controller (MVC) paradigm is a way of splitting up your application so that it's easier to change parts of it without affecting other parts. Before we look at what this means, we need to define these words, which we will do in the context of a user editing employee information on a screen.

<figure><img src="image_27.png" /><figcaption>Figure 23-1. The Employee edit screen.</figcaption></figure>

The *model* is the object or objects that make up the underlying problem domain and is therefore also known as the *domain model*. (The word *domain* is used a lot in Smalltalk applications, and means the realm, area, or field of the underlying problem you are trying to solve.) The model can exist without a user interface, and for the purposes of running regression tests, should probably be able to function without a user interface driving it. In our example, the model is an Employee object. The employee object can exist without a user interface, and in
fact probably spends most of its time without a user interface: either in a database or taking part in report creation and paycheck creation.

The *view* is the presentation to the user of information contained in the model. This usually consists of screens containing information from the model. The data may be shown in fields, in editor windows, in tables, and so on. Also, the data may be read-only or it may be editable. In our example, the view is the employee edit screen, with fields to handle edits to the employee name, social security number, address, and so on.

The *controller* controls the input from the user. The default controllers handle input from the keyboard and from a mouse. Each of the fields on the screen has its own specialized controller, as does each action button, each menu button, etc. Each type of widget has a controller that knows exactly how to handle keyboard and mouse input for that type of widget.

In a normal application, there is a tight coupling between the view and the controller and for most purposes they seem to simply be different behaviors of the same thing. However, by separating the view and the controller, it's possible to give them more powerful behavior by giving them different inheritance hierarchies. It's also makes it possible to create customized controllers for more specialized applications.

## Why is Model-View-Controller important?

Ignoring the controller, which seems to be the poor relative of the three, MVC allows us to separate out our application into two major components that can be replaced or worked on in relative isolation. For example, by separating out the model from the user interface, one set of developers can work on the underlying problem domain, while others can work on the user interface. Obviously there has to be some connection, but MVC makes it a lot easier to separate the work areas. By separating the view from the model, it becomes possible to change the way the model is viewed, and even have multiple views of the model.

Because the view is separated from the model, there has to be a way for the view to tell the model that a user has made changes. Similarly, there has to be a way for the model to tell its view that the model has changed, and that the view needs to update itself with the latest information.

Because there is a separation between the model and the view, with a well-defined way of communicating, this allows multiple views of the same underlying data. For example, suppose you have a spreadsheet open to do some modeling of revenue flows over the next year. Besides the spreadsheet, you also have open a graph showing revenues by month and another graph showing cumulative revenues over the year. As you make changes to the spreadsheet (using a view and a controller), these changes are given to the model, which then tells *all* its views about the changes. The views get the new information and redisplay themselves appropriately. So, as you make changes to the spreadsheet the two graphs are automatically updated.

## How are they tied together?

The mechanism that ties the model and the view together is the dependency mechanism. Each view registers itself as a dependent of the model. The view knows about the model and can therefore directly send messages to the model to update it. However, the model has no direct knowledge about any of the views. The model doesn't care if there are no views, one view, two views, or thousands of views. The only connection between the model and the views is that the model has a collection of dependents that it informs about changes. When the model
changes, it sends out a message to each of its dependents about the change, but neither knows nor cares what the dependents will do with that information. Figure 23-2 illustrates this.

<figure><img src="image_28.png" /><figcaption>Figure 23-2. Model-View-Controller interactions.</figcaption></figure>

In effect, the model says, if you drop your business card in this box, I will send you information about our new products. If you don't want to receive information, take your business card out of the box. Then when there is new information to distribute, it goes to the box and sends the information to everyone whose card is in the box.

## The macro and micro view

There are two ways of looking at MVC: macro and micro. At a macro level, we might have a screen that allows a user to edit employee information. The employee object is the underlying model, while the screen is the view.

At a micro level, the employee edit screen has several input fields — for name, social security number, phone number, address, etc. It may have a menu button for pay grade and a text editor for general notes. Each of these fields is a miniature example of MVC. Each field has a controller associated with it that knows how to handle input to that type of field. Each field has an underlying model, an instance variable of the Employee object. One field may have the employee name as its model, while another field has the employee's social security number as its model. The view is obviously the input field. So, when the user types an employee name, the controller updates the model, the model sends a changed message to its dependents, and the view is updated with the new name. This may seem a little redundant since the view is already showing the name (after all, the user just typed it in), but it allows us to manipulate the data. For example, the user enters the employee's hire date in one of several acceptable date formats. The date will be stored in the employee object as an instance of *Date*. When the view is informed of the change, it may change the date format to a standard display format.

## The ApplicationModel Framework

VisualWorks provides a framework to help manage a user interface application with its many MVC components. This is the *ApplicationModel*. When we create a screen using the Canvas Tool, we have to specify a class to install the canvas on, and this class will usually be a subclass of *ApplicationModel*. In our example, we are using the screen to edit an instance of Employee, so let's call the class *EmployeeUI*. For each variable in the Employee object that we are editing, the *EmployeeUI* class has a corresponding instance variable. This allows us
to separate out the underlying model (the instance of Employee) from the application (the instance of EmployeeUI).

By default, when the user edits data in an input field, the application will modify the data in its instance variable. Let's look at how this works, using an input field that is associated with an employee phone number. Remember that the mechanism at play is that the view (the input field) registers itself as a dependent of the model (the phone number), then gets informed about changes to the model.

## ValueHolder

Our phone number is an instance of *String*. If the view adds itself as a dependent of the string '555-5555', it will never be told of changes. This is because we will not be *modifying* the string, but will be *replacing* it with another string, say '555-1212'. So if the view registers as a dependent of '555-5555', it will still be waiting for '555-5555' to change, which it will never do. In fact, the string won't even be garbage collected since the view is referring to it. This is illustrated in Figure 23-3.

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

<figure><img src="image_30.png" /><figcaption>**Figure 23-3.**
Dependency on a literal value.</figcaption></figure>

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

To solve the problem, we wrap the phone number in a *ValueHolder* and the view registers as a dependent of the *ValueHolder*. The *ValueHolder* has a single instance variable called *value*, which contains the object it is holding — in our case the phone number. To get the phone number, we send the message *value* to the *ValueHolder*, and to set a new phone number, we send the message *value:*. When the *ValueHolder* receives the *value*: message, it stores the new value, then sends itself a changed message, which informs all its dependents of the change. The *value*: method is implemented by a superclass, *ValueModel* and looks like this:

```kotlin
ValueModel>>value: newValue
self setValue: newValue.
self changed: #value
```

Figure 23-4 illustrates the *ValueHolder* mechanism, showing how dependents are informed when a value changes.
<figure><img src="image_32.png" /><figcaption>**Figure 23-4.**
The ValueHolder mechanism.</figcaption></figure>

If you let the Canvas Tool Definer create the application model's instance variables, it will make them ValueHolders. Here's an example of the phone accessor that the Definer will create for you. Notice that the phone number is initialized to a ValueHolder on a new string (`String new asValue`).

phone
> "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method."

^phone isNil
  ifTrue:
    [phone := String new asValue]
  ifFalse:
    [phone]

Thus the `EmployeeUI`'s phone variable contains a `ValueHolder` which is holding a phone string. However, in our `Employee` object, the phone variable contains a string, not a `ValueHolder`. Somehow we have to connect together the phone variable in our `Employee` object and the phone variable in our `EmployeeUI` object.

The easiest approach is to write two methods in `EmployeeUI`, called something like `copyModelToView` and `copyViewToModel`. When we get an `Employee` object to edit, we execute `copyModelToView`, which puts the employee values in the `ValueHolders` in `EmployeeUI`. Then when the user is done editing and wants to save the changes, we execute `copyViewToModel`, which puts the new values into the `Employee` object.

## AspectAdaptor

The `ValueHolder` mechanism suffers from one big disadvantage: the object you care about has to be wrapped in a `ValueHolder`. As we showed above, the easiest way to overcome this is to copy values from the `Employee` object into the `ValueHolders`, then copy them back when the user is finished editing. This means that we have to write specific copying methods.

The class `AspectAdaptor` eliminates this problem. `AspectAdaptors` act as middle-men, removing the necessity to copy values back and forth. The instance variables of our application (our `EmployeeUI`) contains `AspectAdaptors`. When we create each `AspectAdaptor`, we tell it what object we are interested in (the subject, or domain model), and what instance variable of that object (the aspect). In our example, we create an `AspectAdaptor` with the `Employee` object as its subject, and the phone number instance variable as its aspect.
The phone input field then registers as a dependent of the AspectAdaptor. When the user changes the phone number, the input field tells the AspectAdaptor of the change, and the AspectAdaptor sets the new phone number in the employee object. Figure 23-5 illustrates this.

<figure><img src="image_33.png" /><figcaption>Figure 23-5. The AspectAdaptor mechanism.</figcaption></figure>

The change notification can then be done either by the Employee object or the AspectAdaptor. When you create the AspectAdaptor you can specify whether the subject (the employee) sends updates. The default is for the AspectAdaptor to send the update message, which is what we show in Figure 23-5. If the subject sends updates, the AspectAdaptor registers as a dependent of the subject, receives the update messages, filters them, and sends the appropriate ones to its own dependents (ie, the view). If the subject does not send updates, the AspectAdaptor does not register as a dependent. Instead, after setting the new value in the model, it sends the update message itself. Here's the code that does this (AspectAdaptor inherits the code from ProtocolAdaptor).

```ksharp
ProtocolAdaptor>>value: newValue
self setValue: newValue.
subjectSendsUpdates ifFalse: [self changed: #value]
```

## Subject Channels

AspectAdaptors set up a connection between an instance variable of a domain object and a view on a screen. If you are editing an Employee object, each AspectAdaptor is connected to a different instance variable of the Employee. To edit a different Employee object on the same screen means reconnecting each AspectAdaptor to the new Employee. Fortunately, VisualWorks makes it easy to do this using the *subject channel*. Instead of specifying a subject when creating the AspectAdaptor, we specify a subject channel. The subject channel should be a type of ValueModel, which in our example means that we will wrap the Employee in a ValueHolder and specify the ValueHolder as the subject channel.

Each AspectAdaptor registers as a dependent of the Employee ValueHolder, so when the ValueHolder is given a new Employee (by sending `value: anEmployee` to the ValueHolder), the AspectAdaptor is informed of the change in subject. Once it receives notification, it changes its subject. If all the AspectAdaptors are dependents on the Employee ValueHolder, they will all be informed when the Employee changes and will all set the new Employee to be their subject. Figure 23-6 illustrates how subject channels work. Note that step six is only done if the subject sends updates.
<figure><img src="image_34.png" /><figcaption>**Figure 23-6.**
The subject channel.</figcaption></figure>

Using AspectAdaptors and the subject channel mechanism, we can easily associate individual fields on a screen with instance variables of the domain object, and the entire screen with the domain object as a whole.

In the next chapter we'll go over examples of ValueHolders and different types of AspectAdaptor, using code to illustrate how they work.

## Summary

The Model-View-Controller paradigm provides a way to separate out the components of a user-interface oriented application, allowing each component to specialize and to be developed in relative isolation. The VisualWorks user-interface classes are all built around the MVC paradigm, so much of the work has already been done for you. At the micro level, all you really need to do is use the provided classes until you need some specialized functionality.

It is at the macro level that the MVC paradigm really gives you something to think about. It encourages you to think about your domain problem to the point that you can separate out domain objects and domain functionality from the interface with the user. In most cases, the goal of such thinking should be to have a domain model that can be driven from an external source such as a set of batch files, a socket interface, the Transcript, or a test tool. This makes it much easier to test the application. If the domain problem functionality can be driven by these mechanisms then by adding a graphical user interface, you are simply putting in a different view and a different controller.
24

MVC Dependencies

In the previous chapter we talked about the Model-View-Controller philosophy and about how it requires that we break the solution into *model*, *view*, and *controller* pieces, where each piece has relative independence from the others. A key part of MVC is that the views be separated from the model so that a given model can have multiple views looking at it or different aspects of it. To inform all the views of changes in the model, we use the dependency mechanism. In this chapter we take a look at some of the different ways that we can implement the dependencies. In most applications, there is only one view and the view and the controller are tightly tied. Some of the mechanisms we will look at only work in this tight environment and will not support additional views. The more general situation of course, is one where the controller and one view are tightly tied, but other views of the model also exist.

Our example will be a person with a name and an age. The person object is the underlying model. We will allow the user to set or change the name or age using a window with input fields. We also create some additional windows that simply show the values of the person's name and age. The three superclasses for the MyPerson, MyInput, and MyView examples are as follows, showing only the important information.

```
Model subclass: #MyPerson
instanceVariableNames: 'name age '

ApplicationModel subclass: #MyInput
instanceVariableNames: 'person '

ApplicationModel subclass: #MyView
instanceVariableNames: 'person '
```

All the code for these examples is shown in the appendix at the end of the chapter. Enough code is shown in the following text to illustrate certain points, but for more details, you'll need to refer to the chapter appendix. Additionally, you can find the code in the file `mvcdep.st`. Since we are just illustrating points in the text, we'll use only the age variable in our examples.

We will create one window that allows input and several other windows that simply display the data. When we change the name or age in the MyInput window, we expect the MyView windows to update their displays. Unless otherwise noted, all input and view windows have one instance variable, *person*, to hold their model. We
will not show any accessors for *person* to save space, and will reference it directly. Figure 24-1 shows how the windows look when you run the examples.

<figure><img src="image_35.png" /><figcaption>**Figure 24-1.** The view and input windows.</figcaption></figure>

Shown are several examples of different dependency mechanisms. Each is numbered so that, for instance, Example One has a `MyPerson1` model, a `MyInput1` input window, and a `MyView1` display window. Let's start by writing `MyApp`, an application that will run the various examples. Of course, we'll need to write the example code before this code will do anything.

```kotlin
MyApp class>>newExample: aNumber
    ^super new initialize: aNumber

MyApp>>initialize: aNumber
    | model window modelClass inputClass viewClass windowType num |
    num := aNumber printString.
    modelClass := Smalltalk at: ('MyPerson' , num) asSymbol.
    inputClass := Smalltalk at: ('MyInput' , num) asSymbol.
    viewClass := Smalltalk at: ('MyView' , num) asSymbol.
    model := modelClass new.
    1 to: 4 do:
        [ :index |
          windowType := (index == 4)
            ifTrue: [inputClass]
            ifFalse: [viewClass].
          window := (windowType open: model) window.
          window application: self.
          window bePartner]
```

This code opens three `MyView` windows and one `MyInput` window and makes them peers, so that if you close one, they all close. For this to work, you must make sure that `MyApp` is subclassed off `ApplicationModel`. To start up Example1 when you've written the Example1 code, from a workspace evaluate:

```
MyApp newExample: 1.
```

Now we need to create the user interface for our examples. Using the Canvas Tool, create a small window with two input fields: a string field with aspect *name* and a numeric field with aspect *age*. Give the window the label "Input". Install the window on class `MyInput1` and define it as an Application. Modify the window label to
be "View" and make both fields read only, then install it on class MyView1, again defining it as an Application.
All MyView and MyInput examples have a class side method open: as follows.

```perl
open: aPerson
^self openOn: (self new initialize: aPerson)
```

## Example One: Using addDependent:

The basic dependency mechanism is to register as a dependent using `addDependent:`, then to filter the
change notifications in which you are interested. We will take a look at an example using this mechanism, but I
don't particularly recommend it since VisualWorks provides much easier and more powerful mechanisms.

We'll start by looking at how data gets into the application, through the MyInput window. Below is the initialization code for MyInput1. We register ourself as a dependent of the age variable, so that when the age variable changes we'll be told about it (we'll see more about the `onChangeSend:to:` message in a later section).

We are assuming that the MyInput window is the only way that the age and name values can change. If the
application can change a person's data behind the scenes, we would need to have the MyInput window register as
a dependent of the parent, which means we would need extra code to prevent changes sent to us generating
changes back to the model (which would lead to an infinite loop). In reality, we wouldn't be using this
mechanism since better ones exist, as we will see in the other examples.

```perl
MyInput1>>initialize: aPerson
person := aPerson.
age := 0 asValue.
age CHANGE: #ageChanged to: self
```

When the user enters a new age, the MyInput1 object is sent the `ageChanged` message. It then sends a
message to the model — the person — telling it to set its age.

```perl
MyInput1>>ageChanged
person age: self age value
```

When we set a new age in our model, it sends itself a changed message to inform its dependents. We include
the new value so that the dependents don't have to come back and ask us for it. Since no one asks us for the
value, we don't need a get accessor. Note that in Chapter 19, The Dependency Mechanism, we adopted the
convention of sending the *old* value in the changed message. In this chapter, we adopt the alternative convention
of sending the *new* value.

```perl
MyPerson1>>age: aValue
age := aValue.
self changed: #age with: age
```

Here's a diagram showing the mechanism used for notifying dependents when you use the `addDependent:` message.
<figure><img src="image_36.png" /><figcaption>Figure 24-2.</figcaption></figure>

The `addDependent:` mechanism.

The views all register as dependents of the person using `addDependent:`. This means that when the person informs all its dependents of changes, the views will have to filter the update messages to see if they are interested in the change. The `age` variable contains a `ValueHolder` since the input field widget expects to get an instance of a subclass of `ValueModel` when it sends the `age` message.

```groovy
MyView1>>initialize: aPerson
person := aPerson.
person addDependent: self.
age := 0 asValue.

MyView1>>update: aSymbol with: aValue from: anObject
aSymbol == #name ifTrue: [self name value: aValue].
aSymbol == #age ifTrue: [self age value: aValue]
```

## Example Two: ValueHolders

The problem with the basic dependency mechanism of `addDependent:` and `update:` is that we register an interest in hearing about any changes made to the model, then have to filter out the ones we are not interested in. If we had become dependent on the value of the instance variable we were interested in, we would have lost the dependency as soon as the instance variable had a new value. Instead of being dependent on the value, we can wrap the value in a `ValueHolder`, register a dependency on the `ValueHolder`, and be informed every time it gets a new value to hold.

<figure><img src="image_37.png" /><figcaption>Figure 24-3.</figcaption></figure>

The `ValueHolder` mechanism.
If you remember from Chapter 19, The Dependency Mechanism, we can register an interest in changes by sending `onChangeSend/to:` a subclass of `ValueModel`. In Example 2 we make the `age` and `name` variables into `ValueHolders` so that when the actual value changes, the dependents of the `ValueHolder` will be sent the appropriate message.

```kotlin
MyPerson2>>age
^age isNil
    ifTrue: [age := 0 asValue]
    ifFalse: [age]
```

In `MyView2` the `initialize:` method tells the person object's instance variables to send it a message when they change. It then has to implement the methods it has asked to be sent.

```kotlin
MyView2>>initialize: aPerson
    person := aPerson.
    person ageonChangeSend: #ageChanged to: self.
    age := 0 asValue.
```

```kotlin
MyView2>>ageChanged
    self age value: person age value.
```

The model's instance variables are `ValueHolders`, which internally send the message `changed: #value`. This update message is trapped by a `DependencyTransformer` and transformed into the message we specified; in this case `ageChanged`. Because the new value is not passed back, we have to ask the person for the age `ValueHolder`, to which we sent the `value` message to get the new age that it is holding.

Again, I don't recommend using `ValueHolders` as the general mechanism for GUI dependency work because `VisualWorks` provides an easier and more powerful mechanism, `AspectAdaptors`.

## Example Three: AspectAdaptors

Using `ValueHolders` forces domain models to use artificial wrappers around their instance variables for the convenience of any potential GUI. The problem with using `ValueHolders` for the instance variables of your model is that a model models some domain object. Conceptually it has instance variables that are real data, rather than having instance variables that are wrappers of real data.

An `AspectAdaptor` is a powerful mechanism for handling GUI dependencies without forcing the model to use these artificial wrappers around its data. The model has various pieces of information, all contained in different instance variables. `AspectAdaptors` allow you to associate the GUI (`ApplicationModel`) with a particular subject (the model) and different aspects of the subject (the instance variables).
<figure><img src="image_38.png" /><figcaption>**Figure 24-4.** The AspectAdaptor mechanism.</figcaption></figure>

An AspectAdaptor is an easy way to set up an intermediary between the GUI and the model's data. When a user types something in a field in the GUI, the model's data is updated. Also, when the model's data is updated, the views of the data are updated. Let's see how we would code this.

```kotlin
MyInput3>>initialize: aPerson
person := aPerson

MyInput3>>age
^(AspectAdaptor subject: person sendsUpdates: true)
forAspect: #age
```

The code for MyView3 is exactly the same as that for MyInput3 (the only difference is that the fields are read-only).

There are two places we can define the AspectAdaptor: in `initialize` or in the get accessor. To make the examples clearer, we will define it in the accessor. The normal approach to creating the AspectAdaptor is to use the CanvasTool and the Definer. If you select the input fields and press the Define button in the Canvas Tool, this will create the aspect methods for you, which you can then modify to use an AspectAdaptor. Here's an example of what the Definer will create.

```kotlin
age
"This method was generated by UIDefiner. Any edits made here
may be lost whenever methods are automatically defined. The
initialization provided below may have been preempted by an
initialize method."

^age isNil
ifTrue:
    [age := 0 asValue]
ifFalse:
    [age]
```

We would simply assign an AspectAdaptor to the age variable rather than a ValueHolder. In addition to creating the aspect method, the Definer will also create instance variables with the same name. The Definer approach has the advantage that you can send the `age` message more than once with no harmful effects. However, in our application the `age` message is only sent once, by the UIBuilder, when the window is being built. In the interests of saving space we'll take the less safe approach and simply create the AspectAdaptor. Note that by doing this, we don't need the MyInput3 or MyView3 class to have instance variables.
Look again at the AspectAdaptor in the `age` method.

```java
MyInput3>>age
    ^ (AspectAdaptor subject: person sendsUpdates: true) forAspect:
    #age
```

When we create the AspectAdaptor, we tell it what its subject is (the person). We also get to specify whether the subject (the person) sends update messages — ie, whether it does `self changed:`. An AspectAdaptor provides a fairly tight coupling between a field in a window and a value in the model. Since it knows when the model changes, the AspectAdaptor can send the update message. However, the only dependent of the AspectAdaptor is the one field it is tied to. This means that none of the other views will find out about the change. Instead, we want the subject (the person) to send the update messages so that all the views are told the model has changed.

AspectAdaptors by default assume that the aspect is `#value`. Once we have created the AspectAdaptor we tell it to look at the `#age` aspect. To get the age value the AspectAdaptor sends `age` to the model. To set the age value, it sends `age:`. In other words, when you tell it the aspect name, the AspectAdaptor assumes it can send get and set messages using the aspect name and the aspect name with a colon appended. It also assumes that the `changed:` message sends the aspect (ie, the model sends `self changed: #age`).

## Example Four: Subject Channels and differently named accessors

Suppose we want our user interface to look at and be dependent on a different model. In our example, this means that one minute we may be looking at the name and age for John Doe, and the next minute at the data for Nikki Smith. If our AspectAdaptor is dependent on John Doe, we have no way of being informed about updates to Nikki Smith.

Also, the instance variables of the domain model may be accessed using different names than suggested by the aspect (in our example, the accessors will be something other than `age` and `age:`). In this section we will show two ways of modifying AspectAdaptors to handle these two problems.

<figure><img src="image_39.png" /><figcaption>Figure 24-5. AspectAdaptors with a subject channel and different accessors.</figcaption></figure>
To solve the first problem, remember that a `ValueHolder` is a way to wrap a value so that you can be dependent on the `ValueHolder` and be informed when the value it is wrapping changes. In our example, we will wrap the model in a `ValueHolder`, and instead of creating an `AspectAdaptor` with our person as the subject, we will create an `AspectAdaptor` with the `ValueHolder` containing the person as the *subject channel*. Ie, the `ValueHolder` is the channel through which the `AspectAdaptor` talks to the subject (the person). An analogy is the channel at a seance, through whom you can communicate with many different spirits, one at a time.

```kotlin
MyPerson4>>yearsOld
    ^age

MyPerson4>>yearsOld: aValue
    age := aValue.
    self changed: #age

MyInput4>>initialize: aPerson
    "Wrap the model in a ValueHolder"
    person := aPerson asValue

MyInput4>>age
    | adaptor |
    adaptor := AspectAdaptor subjectChannel: person sendsUpdates:
        true.
    adaptor
        accessWith: #yearsOld
        assignWith: # yearsOld:
        aspect: #age.
    ^adaptor
```

The code for `MyView4` is exactly the same as that for `MyInput4` (the only difference is that the fields are read-only). Note that we create the `AspectAdaptor` by sending `subjectChannel:sendsUpdates:` rather than `subject:sendsUpdates:`. This tells the `AspectAdaptor` that the subject is wrapped in a `ValueHolder`. Again, the subject sends the changed messages otherwise not all the `AspectAdaptors` will be informed.

Notice that we tell the `AspectAdaptor` what accessors to use to get and set the person's data. This solves the second problem we described above, that the accessors may have different names than the name suggested by the aspect.

## Example Five: Delaying updates

<figure><img src="image_40.png" /></figure>
**Figure 24-6.** The BufferedValueHolder mechanism.

In the examples so far, whenever you changed the person's name or age, the change was immediately reflected in the other windows. However, in an application, you may want to present a screen with the data, let the user make changes to multiple fields, then update the model and other views all at once.

The MyInput5 ApplicationModel no longer has a simple AspectAdaptor sitting as intermediary between the field and its model's data. Instead, it adds a BufferedValueHolder between the field and the AspectAdaptor and talks to the BufferedValueHolder. The BufferedValueHolder registers as a dependent of a special *trigger* ValueHolder. When the trigger value changes, the BufferedValueHolder is informed, and if the trigger value is *true* the BufferedValueHolder talks to the AspectAdaptor, which then talks to the model (the person), setting the data appropriately.

```java
MyInput5>>age
| adaptor |
adaptor := AspectAdaptor subject: person sendsUpdates: true.
adaptor forAspect: #age.
^BufferedValueHolder subject: adaptor triggerChannel: trigger.
```

You will need to modify the MyInput5 canvas to also have an Accept button, with an action of `accept` (you can call it whatever you want as long as you give the action method the same name). Also, MyInput5 will now have an instance variable called `trigger` which will hold a `ValueHolder`. MyInput5 sets the trigger value to `false` during initialization. When the value is set to `true`, the AspectAdaptors will do their work of taking the values in the user interface fields and using them to set the person's data. The trigger is set to `true` when the user presses the Accept button.

```java
MyInput5>>initialize: aPerson
person := aPerson.
trigger := false asValue

MyInput5>>accept
"The user has accepted the data. Set the trigger to true to update
the model"
trigger value: true
```

Since the view window is not setting the data, it doesn't need to have triggers and BufferedValueHolders. Instead, it uses a basic AspectAdaptor as in Example Four.

Using BufferedValueHolders, the user can now edit many fields on a form but not have the model updated until they commit the changes (for example, by pressing the Accept button). Unfortunately, a BufferedValueHolder suffers from a serious drawback: it does not get cleared or updated when its subject changes. A better mechanism for editing domain objects is to make a copy of the domain object and use AspectAdaptors to connect between the user interface and the domain object. We cover this briefly in Chapter 27, Extending the Application Framework.
## Example Six: Aspect Paths

<figure><img src="image_41.png" /><figcaption>Figure 24-7. Specifying an Aspect Path.</figcaption></figure>

Despite the relative ease of setting up an AspectAdaptor, you might wonder why it's not easier still. In fact, it can be very easy. Using *aspect paths*, we can eliminate all the methods that created AspectAdaptors in the previous examples. Instead, we use the Canvas Tool to specify the aspect path. When building the window, we can specify in the Properties Tool the path to the variables we want associated with each field.

In the Aspect fields in the Properties Tool type `person age` and `person name`. This specifies the paths to use to access the data in the model. The underlying model will be accessed through the accessor `person`. To get the age and name data, the user interface builder will generate code to send the messages `age` and `name` to the person — ie, it will send the messages `person age` and `person name`. To set the data, it adds a colon to the end of the message thus sends `person age:` and `person name:`. (You can specify a path that consists of several messages if necessary. For example, if the person had an address object which consisted of street name and town, you could edit these fields by using an aspect path of `person address street` and `person address town`.) Note that using aspect paths violates encapsulation because you are giving the user interface knowledge of the domain model's methods. The more method names you specify in the path, the worse the violation.

If you ask the Definer to define these fields, it will create a single access method for the model, `person`. Below are all the methods that are needed. The code for `MyView6` is the same as the code for `MyInput6` apart from the read-only fields. Note that the model (ie, the `person`) needs to be wrapped in a `ValueHolder` if you want to use aspect paths.

```java
MyInput6>>initialize: aPerson
person := aPerson asValue.

MyInput6>>person
^person

MyPerson6>>age
^age
```
MyPerson6>>age: aValue
age := aValue.
self changed: #age

When you run this, you will find that the view windows are *not* updated when you type in the input window. Aspect paths are very easy to create, but their downside is that they provide very tight coupling between the model, view, and controller. When you type (using the controller), the model is automatically updated, and the view is automatically informed and updated.

(When you use aspect paths, AspectAdaptors are created for you when the code runs. Because you have no control over how the AspectAdaptors are created, you can't get them to understand the update messages sent by the model. All the *changed* message code is done behind the scenes, out of your control. Thus the *self changed: #age* in the *age:* method doesn't do anything. However, it's worth leaving in because the model doesn't know how the views will register their dependency, and there may be some views that rely on it.)

The bottom line is that if you have a user interface with a single view of the data (ie, very tight coupling between the model, the view, and the controller), aspect paths are a very convenient way to go. If you want multiple views of the data, use another mechanism. (It's possible to use aspect paths for the input window and another mechanism for the read-only views.)

## Example Seven: Buffered Aspect Paths

In Example 5, we saw how to use BufferedValueHolders to delay updating the model's data until the user indicates that everything is correct by pressing the Accept button. In Example 6, we used aspect paths to simplify the code, and had very little software to write. Now we combine BufferedValueHolders and aspect paths to provide a way to buffer input with very little code writing.

<figure><img src="image_42.png" /><figcaption>Figure 24-8. Specifying a Buffered Aspect Path.</figcaption></figure>

In MyInput7, create an Action button labelled 'Accept' with an action of *accept*. In the Aspect fields in the Properties Tool type `person age | trigger` and `person name | trigger` for the appropriate input fields. The message name after the vertical bar, `trigger`, is the message that is sent to get hold of the
ValueHolder holding the trigger. We initialize the trigger to false, and when the user accepts the data, we set it to true. This tells the generated code to go ahead and update the model's data.

The code for MyView7 looks exactly like the code for MyView6 since we don't need to do buffering on the View windows. As in Example 6, the model (ie, the person) needs to be wrapped in a ValueHolder. And, as in Example 6, when you run Example 7, you will find that the view windows are *not* updated when you type in the input window. Again, this is because of the tight coupling between the model, view and controller that you get when you let VisualWorks generate all the AspectAdaptor code.

MyInput subclass: #MyInput7
instanceVariableNames: 'trigger '

MyInput7>>initialize: aPerson
person := aPerson asValue.
trigger := false asValue.

MyInput7>>person
^person

MyInput7>>trigger
^trigger

MyInput7>>accept
trigger value: true.

When you run this you will see no difference between Example 6 and 7 because in both examples, the input
window shows what you have typed but the views don't change. How can you tell whether the data really is
being buffered until the user presses Accept? We show this by writing to the Transcript when the person's data
changes

MyPerson7>>age: aValue
age := aValue.
Transcript cr; show: 'Age changed'.
self changed: #age

Example Eight: PluggableAdaptors

<figure><img src="image_43.png" /><figcaption>**Figure 24-9.** The PluggableAdaptor mechanism.</figcaption></figure>

A PluggableAdaptor is the most powerful type of adaptor, because it lets you manipulate the model's data when getting it from the model and when setting it in the model. Why would you want to do this? You might
want to convert input to a standard format before storing it. Or perhaps you have stored a date and want to
display it according to some user defined format.

Our model, the person, has basically the same methods we saw in the previous examples. The only difference
is that we want to initialize the age to a meaningful value rather than letting it default to nil, because in our
example we manipulate the data before displaying it.

MyPerson8>>age
^age isNil
    ifTrue: [age := 0]
    ifFalse: [age]
MyPerson8>>age: aNumber
age := aNumber.
self changed: #age

The Input window creates a PluggableAdaptor for each field (name and age). The subject of the PluggableAdaptor (the parameter to on:) is the model (the person), and the get and put blocks tell how to get and set the particular instance variable of the person. For the Input window we are doing some manipulation of the data before storing it in the model: we are multiplying the age by three.

MyInput8>>initialize: aPerson
person := aPerson.
MyInput8>>age
^(PluggableAdaptor on: person)
  getBlock: [:model | model age]
  putBlock: [:model :aValue | model age: aValue * 3]
  updateBlock: [:model :aspect :parameter | aspect == #age]

The update block tells the PluggableAdaptor whether to execute the get block and update the field in the user interface. The get block is executed if the block returns *true*. In the PluggableAdaptor above, since the PluggableAdaptor is interested in the person's age variable, it only cares when the age changes — ie, when the person does self changed: #age. So it tests to see if the aspect it received is the one it is interested in, #age. Similarly, the *name* PluggableAdaptor will check to see if the change was associated with the #name symbol.

The View window has exactly the same `initialize:` method as the Input window, but the PluggableAdaptors are slightly different because the View window can't change the data and so doesn't have to worry about the put block.

MyView8>>age
^(PluggableAdaptor on: person)
  getBlock: [:model | model age * 10]
  putBlock: [:model :aValue | ]
  updateBlock: [:model :aspect :parameter | aspect == #age]

The put block doesn't do anything because the View doesn't update the model. It still has to check for the aspect that changed so the update block is the same as for MyInput8. The get block multiplies the model's value by ten before it gets displayed.

When you run Example 8, the age will be multiplied by three before storing it in the model. Because the value has changed, the age field in the MyInput window will be updated, showing three times what you typed. In
the MyView windows the age will be ten times the value stored in the model — thirty times what you typed. The name you typed will be lowercased before storing it in the model and will therefore display as lowercase in the MyInput window. In the MyView windows the name will be all uppercase.

One thing to note in this example is that we created the PluggableAdaptor on the model. When the model sends itself a *changed* message after one of its instance variables is changed, all the PluggableAdaptors get sent the *update* message. They use the update block to find the particular change they are interested in. So there is the potential for a lot of redundant message sends since each PluggableAdaptor will receive all the *update* messages even though it is not interested in most of them.

## Summary

* The `addDependent` message provides the basic dependency mechanism. It suffers from the disadvantage that all dependents get all update messages and have to filter out what they want. VisualWorks provides better mechanisms.

* `ValueHolder` provides a cleaner interface. It provides the ability to inform dependents of only the specific changes they are interested in. It has the disadvantage that models must wrap their data in `ValueHolders`.

* `AspectAdaptor` provides a better still interface because it sits between the user interface widget and the model's data. The model does not have to wrap its data in `ValueHolders`.

* `BufferedValueHolder` provides a way to delay updating the model until the user chooses to commit the changes. It is a wrapper around all the `ValueHolders` or `Adaptors` that should be grouped together in a single update.

* `Aspect Paths` make it easy to set up `AspectAdaptors` using the `CanvasTool` rather than having to write methods. They have the disadvantage that there is a very tight coupling between the model, controller, and view, and they cannot update other views.

* `Buffered Aspect Paths` combine the buffering of `BufferedValueHolder` with the ease of creation of `Aspect Paths`. Again, there is a very tight coupling between the model, view and controller.

* `PluggableAdaptor` provides a very powerful mechanism to modify data either on its way from the view to the model, or on its way from the model to the view.
25

Hooks into the System

Smalltalk provides various hooks into the system that allow you to do additional processing on top of the
system provided behavior. The two areas that you are most likely to need these hooks are when copying objects
and when opening and closing an application with a user interface. However, as you dig through the class
library, you will inevitably find additional hooks, and these will inevitably give you ideas on new features you
can add to your applications, or new ways of structuring your applications. Since most of this chapter describes
user interface hooks, it is located in the User Interface section, despite the more general section on copying.

Copying

postCopy

When you send the copy message to an object, it returns a copy of itself. However, it returns what is known
as a shallow copy. You have a new instance of the object's class, but the instance variables in the copy contain
exactly the same object as in the original. So, if you change part of one of the instance variables in the copy, the
original gets the same change. Let's look at an example. Create two classes, Person and Address, as shown below
(you can find the code in the file copydemo.st). Add accessors to all the instance variables. If you then run
the code that follows, you will see that the street address of personOne is '221 Jones Court', which is not what
you want.

Object subclass: #Person
instanceVariableNames: 'name address '

Object subclass: #Address
instanceVariableNames: 'streetAddress city '

(address := Address new)
streetAddress: '916 Smith Avenue';
city: 'Boulder'.
(personOne := Person new)
name: 'Alec Sharp';
address: address.

Copyright © 1997 by Alec Sharp

Download more free Smalltalk-Books at:

- The University of Berne: http://www.iam.unibe.ch/~ducasse/WebPages/FreeBooks.html

- European Smalltalk Users Group: http://www.esug.org
personTwo := personOne copy.
personTwo address streetAddress: '221 Jones Court'.
personOne address streetAddress inspect

The reason for the unexpected result is that *Object* basically implements *copy* as *shallowCopy*. The comment for *shallowCopy* says "Answer a copy of the receiver which shares the receiver's instance variables." Fortunately, *copy* also provides a hook so that you can do further processing if a shallow copy is not adequate. The actual implementation of *copy* looks like the following.

Object>>copy
^self shallowCopy postCopy

This gives us an opportunity to get the behavior we want by implementing the method `postCopy`, in which we can make copies of the instance variables. When you implement `postCopy`, you should always do `super postCopy` in case one of your superclasses needs to do something. We want to make a copy of the *address* object so that we don't see the behavior shown above. If you implement the `postCopy` shown then rerun the above code, you'll see that `personOne` still has a street address of '916 Smith Avenue'.

Person>>postCopy
super postCopy.
address := address copy

Other uses for `postCopy` include situations where you need to reset something after copying an object. For example, when you copy an instance of *Model*, the copy does not get the list of dependents.

Model>>postCopy
super postCopy.
self breakDependents

(VisualWorks used to provide a `deepCopy` which recursively copied the instance variables as well. However, the implementation could lead to problems when objects pointed to each other. In *The Journal of Object-Oriented Programming*, September 1994, Wilf Lalonde and John Pugh describe a partial implementation of a `deepCopy`.)

## copyEmpty:

While it's not very common, you can create a class that is a subclass of a collection class, and add new instance variables. As you add items to your collection, it may need to grow in size. The way this happens is that a new collection object is created, the collection items are copied across, then the old object *becomes* the new object. Unfortunately, your instance variables are not copied across into the new object. Here's an example that illustrates this. The following code creates an instance of *MyClass* with a size of two, sets the two instance variables, then adds three items to the collection. Since the collection has a size of two, it has to grow. You'll need to write accessors for the variables.

Set variableSubclass: #MyClass
instanceVariableNames: 'varOne varTwo '
coll := MyClass new: 2.
coll varOne: 1.
coll varTwo: 2.
coll add: 22; add: 33; add: 44.
coll inspect

When you inspect the collection, you will find that your instance variables no longer have the original values.
Fortunately there is a hook that lets you copy them across. To get them, you must override Collection's
`copyEmpty:` method. Here's an example of how you might do this.

MyClass>>copyEmpty: newCapacity
^(super copyEmpty: newCapacity)
    varOne: self varOne;
    varTwo: self varTwo;
    yourself

## User interface opening

When you open an application (ie, a subclass of ApplicationModel), there are several places where you can
do additional processing. If you say `MyApplication open`, there are various hooks that give you the
opportunity to set things up according to the needs of your application. In order, the following messages will be
sent: `initialize`, `preBuildWith:`, `postBuildWith:`, and `postOpenWith:`. We'll look at each in
turn, but if you decide to override them, the first thing in your method should be a message send to *super* so that
the inherited method is also invoked. Here's what the fundamental interface opening method looks like. Notice
that this method directly does three of the message sends just mentioned.

ApplicationModel>>openInterface: aSymbol
| spec |
builder := UIBuilder new.
builder source: self.
spec := self class interfaceSpecFor: aSymbol.
self preBuildWith: builder.
builder add: spec.
self postBuildWith: builder.
builder window model: self.
builder openWithExtent: spec window bounds extent.
self postOpenWith: builder.
^builder

In what follows, we will use the example of a window with two action buttons and two input fields. The
action button actions are *actionOne* and *actionTwo* and their IDs are *actionOneAB* and *actionTwoAB*. The input
fields have aspects of *inputOne* and *inputTwo*, with IDs of *inputOneIF* and *inputTwoIF*. If you create the
window and the appropriate methods, you can see that how this all works. The code can be found in the file
hooks.st.

### initialize

The initialize method is where we usually set up the various ValueHolders for the aspects, assuming we don't
want to use lazy initialization. In our example we will also set the field data.

MyClass>>initialize
super initialize.
inputOne := 'Text in input field one' asValue.
inputTwo := 'Text in input field two' asValue
## preBuildWith: aBuilder

The `preBuildWith:` method allows you to change the way that the user interface will be built. The builder uses the spec that it is supplied with (usually `#windowSpec`, which is the symbol used if the `open` message is sent), but in this method you can override the description contained in the spec. For example, we want to change the way the action buttons work. Instead of invoking the specified method when the button is invoked, we want to invoke the same method but with a different parameter. We can set this up in `preBuildWith:`. We specify a block of code that should be executed when the button is pressed.

```myclass
MyClass>>preBuildWith: aBuilder
    super preBuildWith: aBuilder.
aBuilder actionAt: #actionOne put: [ self doAction: #one ].
aBuilder actionAt: #actionTwo put: [ self doAction: #two ].
```

We could also set up blocks of code to build menus every time a menu button or a pop-up menu is selected. This would allow us to dynamically change the menu based on varying conditions. For example, we might have code such as the following, where `buildInputOneMenu` is invoked every time the user wants to see the menu.

```myclass
aBuilder menuAt: #inputOneMenu put: [self buildInputOneMenu]
```

## postBuildWith: aBuilder

In `postBuildWith:` we can make changes to the interface after it's built but before it is displayed. In our example, we will set the label of one button and the visibility of the other button. These actions can only be taken after the window is built.

```myclass
MyClass>>postBuildWith: aBuilder
    super postBuildWith: aBuilder.
self invisibleButton
    ifTrue:
        [(aBuilder componentAt: #actionOneAB) labelString: 'Yes'.
         (aBuilder componentAt: #actionTwoAB) beInvisible]
    ifFalse:
        [(aBuilder componentAt: #actionOneAB) labelString: 'No'.
         (aBuilder componentAt: #actionTwoAB) beVisible]
```

## postOpenWith: aBuilder

In `postOpenWith:` we can do things that require the screen to already be displayed. In our example, we specify which input field should have the focus — ie, which field the cursor should appear in, and where to position the cursor in the field.

```myclass
MyClass>>postOpenWith: aBuilder
    super postOpenWith: aBuilder.
self invisibleButton
    ifTrue:
        [component := aBuilder componentAt: #inputOneIF.
         component takeKeyboardFocus.
         component widget controller selectAt: self inputOne value
         size + 1]
    ifFalse:
        [component := aBuilder componentAt: #inputTwoIF.
```
component takeKeyboardFocus.
component widget controller selectAt: 1]

## Support methods

Here is sample code for the other methods we need to write.

MyClass>> invisibleButton
"Requires an instance variable called invisibleButton"
^ invisibleButton isNil
ifTrue: [invisibleButton:= Dialog confirm: 'Invisible button?']
ifFalse: [invisibleButton]

MyClass>>doAction: aSymbol
Transcript cr; show: 'Action ', aSymbol

MyClass>>inputOne
^inputOne

MyClass>>inputTwo
^inputTwo

## User Interface closing

Just as there are places you can add code during the creation and opening of windows, there are places you can add code when they are closing. In particular, we will look at how you are informed that someone wants to close the window, and that the window is closing. To close a window the usual way, you send the application a `closeRequest` message (if you add a Cancel button using the Canvas Tool, you can put `closeRequest` in the Action field in the Properties Tool). The `closeRequest` message puts a close event on the event queue, as if the user had used the native window manager facilities to close the window. If you are writing a normal application subclassed off ApplicationModel, both `changeRequest` and `requestForWindowClose` messages will be sent by the window controller (an ApplicationStandardSystemController). The window will only be closed if both messages return `true`. The actual message sends are shown below, and although `requestForWindowClose` is sent to `self` (the controller), the `requestForWindowClose` method sends the same message on to the application model. Thus, the application model is sent both `changeRequest` and `requestForWindowClose`.

model changeRequest ifFalse: [^false].
self requestForWindowClose ifFalse: [^false].

Your application may need to add its own check to see whether it's okay to close the window. Typically, you will check that the user is not in the middle of editing data. If there are uncommitted changes, you'll probably prompt the user to save them. To do this checking, you can override either `changeRequest` or `requestForWindowClose`. Your method should first send the same message to its superclass, then do any application specific checking, returning `true` if it's okay to close the window, and `false` otherwise.

### changeRequest

The `changeRequest` message is sent when something wants to change and is trying to find out if it's okay to change. In our case the change is quite drastic — we want to close the window. The window's controller sends
`changeRequest` to the application model, asking if the application model gives permission for the change (ie, the close). The inherited implementation of `changeRequest` sends an `updateRequest` message to all the dependents of the application model, asking whether they think that it's okay to change. So, `changeRequest` just checks with all the application model's dependents.

We can override `changeRequest` to add our application checks, making sure that the superclass's method is still invoked. Returning `true` now means that both the application model and its dependents agree to the change. Here's an example.

```
MyClass>>changeRequest
    super changeRequest ifFalse: [^false].
    ^self hasUncommittedChanges
    ifTrue: [self checkCloseWithUser]
    ifFalse: [true]
```

In fact, returning `true` simply says that from the perspective of the application model and its dependents, it's okay to change. The controller will then check with the keyboard processor to make sure that there are no fields needing validation. So it's possible the window will not close even though you return `true`. In VisualWorks 1.0, overriding `changeRequest` was the standard technique for adding your own logic to see if the window may be closed. However, since the window might remain open even though you return `true`, it's a better technique to override `requestForWindowClose`, which was added in VisualWorks 2.0.

### requestForWindowClose

After sending `changeRequest`, the window controller then sends the `requestForWindowClose` message to its application model, which checks to see if the keyboard processor thinks it's okay to close the window. If the keyboard processor returns `true`, no other checking will be done, and the window will be closed. This is therefore a good time to do your application checking. Here's an example.

```
MyClass>>requestForWindowClose
    super requestForWindowClose ifFalse: [^false].
    ^self hasUncommittedChanges
    ifTrue: [self checkCloseWithUser]
    ifFalse: [true]
```

Overriding `requestForWindowClose` is now the recommended technique for adding your own checking to see if the window is allowed to close.

### noticeOfWindowClose:

When a window closes, its application model will be sent the message `noticeOfWindowClose:`. If your application inherits this from `ApplicationModel`, the method simply returns `self`. However, you can override `noticeOfWindowClose:` if you want to do something specific when the window closes. For example, when I open windows from other windows, I set up a parent-child relationship. This is different from the VisualWorks master-slave relationship because in the master-slave relationship a slave can't be a master in another relationship, whereas a window can simultaneously be the child of one window and the parent of another window. When a parent window closes, it closes all its children. Here's an example of how this works, using the `noticeOfWindowClose:` message.
MyApplication>>requestForWindowClose
^super requestForWindowClose
ifTrue: [self childApplicationsCanClose]
ifFalse: [false]

MyApplication>>childApplicationsCanClose
"We don't know if child applications will override changeRequest
or requestForWindowClose, so we'll check both."
| childrenThatCantClose |
childrenThatCantClose := childApplications
  select: [:each | each changeRequest == false
          or: [ each requestForWindowClose == false]].
^childrenThatCantClose empty

MyApplication>>noticeOfWindowClose: aWindow
super noticeOfWindowClose: aWindow
self parentApplication notNil
ifTrue: [self parentApplication removeChild: self].
childApplications do:
  [:each | "Don't send closeRequest to subcanvases"
     each builder window == self builder window
     ifFalse: [each closeRequest]]

In Chapter 27, Extending the Application Framework we talk about extending the VisualWorks ApplicationModel. The code shown above extends the extensions we discuss in Chapter 27 and can be found in the fileframewrk.st.
26

ChangingWidgets at Runtime

This chapter contains information on changing VisualWorks widgets while the application is running. For
example, it describes how to change labels, how to disable action buttons, and how to make fields invisible. It is
by no means a complete description of even this small aspect of VisualWorks, but it should give you some ideas
of things you can do in your application and places to look when you want to do more.

When we build a user interface, we place *widgets* on the canvas: action buttons, input fields, labels, etc. Each
widget has a *controller* that handles input to the widget. The widget also has a wrapper that handles how the
widget is presented to the user. The User Interface *builder* keeps track of all these wrappers, referring to them as
*components*. Let's take a quick look at these four aspects of building an application.

The builder

Every subclass of *ApplicationModel* (ie, every window-based VisualWorks application) has a user-interface
builder. This builder knows how to construct the user-interface, but, more importantly for us here, it keeps track
of all the components of the user-interface. Within the subclass of *ApplicationModel*, the builder can always be
referenced as:

`builder := self builder.`

Components

The canvas that you construct consists of a group of components. The component is actually a *wrapper* around the widget that you added (such as an action button, a label, an input field, etc.) To reference one of these components, it has to have an ID, which you specify in the ID field in the Properties Tool. I tend to give the component an ID that describes the type of the widget. For example, an action button might have the ID *saveAB*, where the AB specifies that it is an action button. Similarly, an input field might have an ID of *employeeNameIF*. To get the component, our application model asks its builder for the component at the ID we are interested in. For example,

`component := self builder componentAt: #employeeNameIF.`

Copyright © 1997 by Alec Sharp

Download more free Smalltalk-Books at:

- The University of Berne: http://www.iam.unibe.ch/~ducasse/WebPages/FreeBooks.html

- European Smalltalk Users Group: http://www.esug.org
Since the component is a wrapper around a widget, you will sometimes see the above code written as:

wrapper := self builder componentAt: #employeeNameIF.

Components/wrappers understand how to make themselves visible and invisible, or enabled and disabled.
You can tell them to take the keyboard focus, you can change their label strings, and you can set their colors (via
their look preferences). We'll see examples of these later.

Widgets

The widget is the object that you think of when you talk about things such as action buttons, input fields, and
labels. For active widgets such as these, the widget is actually a view, such as an ActionButtonView. The
component is the wrapper around the widget. To get the widget, you simply send the widget message to the
component. For example,

widget := (self builder componentAt: #employeeNameIF) widget.

If you inspect a widget that is a view, you'll notice that it has instance variables for its model and controller.

Controllers

Each widget has a controller that handles the keyboard and mouse input. In particular, for input fields, the
controller handles the text in the field, the cursor position, and the selection. To get the controller, you send the
controller message to the widget. For example,

controller := (self builder componentAt: #employeeNameIF) widget
controller.

If you use the Properties tool to set up a notification or validation method and specify a keyword method with
one colon, the parameter to the method will be the controller. So, rather than having to get the controller via
something like the above, you will be passed it directly as a parameter. You can then get the new text directly
from the controller. For example, your validation method might look like:

MyClass>>validateName: aController
newText := aController text.
... do some validation then return true or false...

Another thing to be aware of in validation methods is how to discover if user input has been accepted. If you
set up an input field to be, say, a date or time, VisualWorks will flash the field if the data is invalid, but will let
the user proceed. To tell if the data is valid (ie, it was successfully converted), send the controller the message
hasEditValue, which returns a Boolean (you can also send this message to the widget). For example,

^aController hasEditValue
ifTrue: [true]
ifFalse:
    [Dialog warn: 'Invalid date'.
     false]
Before we leave the topic of validation, one thing I find frustrating about the validation mechanism is that
there is no way to know which widget the user wants to pass focus to when you are in a validation routine. For
example, suppose you have a field that requires valid input, such as a date field. If the user can't figure out what
to enter and they press the Cancel key, the application still tries to validate the input. So the user can't cancel
until they either enter valid data or blank out the field. One solution is to modify `KeyboardProcessor`. Add an
instance variable called, say, `controllerRequestingFocus`, and a get accessor for it. In the method
`KeyboardProcessor>>requestFocusFor:`, add the following line just before sending the
`requestFocusOut` message to the current consumer.

controllerRequestingFocus := aController.

Now, in your validation routine you can have something like the following. Each validation method may
want to check if the cancel key has been pressed, so we break out that code into a separate method. There is an
example of this in the file focus.st.

MyApplication>>validateDate: aController
self cancelPressed ifTrue: [^true].
^aController hasEditValue
ifTrue: [true]
ifFalse:
    [Dialog warn: 'Please enter a valid date'.
    false]

MyApplication>>cancelPressed
^self builder keyboardProcessor controllerRequestingFocus ==
(self builder componentAt: #cancelAB) widget controller

Modifying things

Now that we have a small amount of background, we can go ahead and show the code for doing various
runtime changes. Examples of this can be found in the file `widgets.st` on the diskette. This first example is
the class `WidgetAttributes`.

Enabling and Disabling

To enable and disable a widget we send the `enable` and `disable` messages to the component. When a
widget is disabled, it appears grayed out to indicate that it can't be used. For example,

(self builder componentAt: #saveAB) enable.
(self builder componentAt: #saveAB) disable.

Visible and Invisible

We make a widget visible or invisible by sending the messages `beVisible` and `beInvisible` to the
component. For example,

(self builder componentAt: #salaryIF) beVisible.
(self builder componentAt: #salaryIF) beInvisible.
<figure><img src="image_44.png" /><figcaption>**Figure 26-1.** Dynamically modifying widget attributes.</figcaption></figure>

## Changing labels

To change the label string on a widget, we send the `labelString:` message to the component. For example,

```
(self builder componentAt: #actionAB) labelString:
  (mode == #edit)
    ifTrue: ['Save']
    ifFalse: ['Add'].
```

Unfortunately, getting the label string is not quite as easy. We have to get it from the widget itself via several message sends. For example,

```
labelString := (self builder componentAt: #actionAB) widget label
  text asString.
```

## Changing selections and cursor position

Selections and cursor position are associated with controllers, so to manipulate them we need to send messages directly to the controller. To make a widget be the active widget, send the `takeKeyboardFocus` message to the controller. In the case of an input field, this will also select and highlight all the text in the field. For example,

```
controller := (self builder componentAt: #salaryIF) widget
  controller.
  controller takeKeyboardFocus.
```
If you send `takeKeyboardFocus`, you don't need to specifically select the text. However, you can alternatively select a range of characters, or position the cursor at a particular location. Here are some examples,

```javascript
controller selectFrom: 3 to: 5.
    "Select and highlight from position 3 to 5"
controller selectAt: 1.
    "Position the cursor at the beginning"
controller selectAt: controller text size + 1.
    "Position the cursor at the end"
controller find: 'and' startingAt: 1.
    "Position the cursor before 'and'"
controller findAndSelect: 'and'.
    "Find the word 'and' after the current selection, and
    highlight it"
```

Two additional messages, `select` and `deselect`, `highlight` and `unhighlight` the selected text. They do *not* change the selection. To retrieve the currently selected text, send `selection` to the controller.

## Changing colors and fonts

In the following example class, `WidgetText`, we look at changing colors, fonts, and emphases. This class can be found in the file `widgets.st`.

<figure><img src="image_45.png" /><figcaption>Figure 26-2. Dynamically modifying widget text.</figcaption></figure>

There are several aspects to changing colors and fonts. To change *colors* such as the background colors and foreground colors of widgets, we have to get the component's look preferences (actually, the `lookPreferences` messages returns a copy of the look preferences). We then set the colors appropriately and give the new look preferences to the component. The `lookPreferences:` message tells the component that the look preferences have changed, so the component redisplays itself. For example,

```javascript
component := self builder componentAt: #saveAB.
look Preferences := component lookPreferences.
```
```kotlin
lookPrefs setForegroundColor: ColorValue green.
component lookPreferences: lookPrefs.
```

To change the *text attribute* of a widget, we create an instance of *TextAttributes*. We'll use a default style named `#large`, although you get more flexibility by creating an instance of *TextAttributes* using *CharacterAttributes*. We replace the style rather than modifying the one we have because it may be one that this widget shares with other widgets. If we changed the style directly, the other widgets would also get the change. Note that we invalidate the widget afterwards, which causes it to redisplay itself.

```kotlin
widget := (self builder componentAt: #saveAB) widget.
widget textStyle: (TextAttributes styledNamed: #large).
widget invalidate.
```

To change the *text emphasis* for widgets with labels, such as an action button or a label, we can do something like the following. We get the label text and emphasize it by passing either an array of emphases or a single emphasis. Then we set the label's text to be the newly emphasized text.

```kotlin
widget := (self builder componentAt: #saveAB) widget.
emphasis := Array
  with: #italic
  with: #large
  with: #color -> ColorValue pink.
newText := widget label text emphasizeAllWith: emphasis.
widget label text: newText.
widget invalidate.
```

If we want to emphasize text in an input field, the approach is very similar, but we get the text from the controller rather than from the label. For example,

```kotlin
widget := (self builder componentAt: #nameIF) widget.
widget editText: (widget controller text emphasizeAllWith: #(#italic
#large).
widget invalidate.
```

A shortcut for bold text is to send the message `allBold` to the text. Note that in the *WidgetText* class provided in `widgets.st`, the label fields have been lengthened. Without the lengthening, the old text is not completely cleaned up when the text size changes to a smaller size.

## Changing Menus

In this section, we'll take a look at three different kinds of menus: menu bars, menu buttons, and text field menus. For each of these menu types we want to do three different things. First, we want to replace the menu with a completely different menu based on some event. Second, we want to dynamically select the menu to present when the user goes to select a menu item. Third, we want to modify the menus, disabling menu items, hiding items, changing colors, and adding items. Examples of the following can be found in *MenuDynamicModify* and *MenuDynamicCreate* in the file `widgets.st`. The first example, *MenuDynamicModify*, shows various modifications you can make to a menu.
<figure><img src="image_46.png" /><figcaption>**Figure 26-3.** Dynamically modifying menus.</figcaption></figure>

## Replacing menus

When we create a menu, we specify a method in the Menu field in the Properties Tool. Usually this method is invoked once by the builder, returns a menu, and is never invoked again. To make it possible to replace the menu, we instead specify a method that returns a *ValueHolder*. The *ValueHolder* holds a menu, and by sending the `value: aNewMenu` message to the *ValueHolder*, we can replace the menu completely. For example, in the `initialize` method we might have something like:

initialize
menuButton := nil asValue.
inputField := String new asValue.
menuButtonMenuVH := self menuOne asValue.
inputFieldMenuVH := self menuOne asValue.
MenuBarVH := self class menuOne asValue.

Then at any point in the program, we can install a new menu by doing the following.

menuButtonMenuVH value: self menuTwo.
inputFieldMenuVH value: self menuTwo.
MenuBarVH value: self class menuTwo.

## Modifying menus and menu items

To modify a menu or menu item, we first need to get the menu (for the menu bar, I am assuming that we are modifying one of the pull-down menus). There are two basic ways to get the menu from the builder. One way gets it via the component: from the widget for a *menu button*, from the controller for a *text field*, and for a menu bar we get the submenu by specifying the main menu item, then asking for its submenu.

menu := (self builder componentAt: #departmentMB) widget menu.
menu := (self builder componentAt: #nameIF) widget controller menu.
menu := (MenuBarVH value menuItemLabeled: 'Select') submenu.
The other way of getting the menu is via the method specified in the *Menu* field of the Properties Tool. If the method gives back a menu, then we do the first line below. If the method gives back a *ValueHolder*, we do the second line. In both cases the parameter to `menuAt:` is the name we specified in the *Menu* field of the Properties Tool.

```kotlin
menu := self builder menuAt: #menuButtonMenu.
menu := (self builder menuAt: #menuButtonMenuVH) value.
```

Once we have the menu, we get the menu item we want to change by sending the `menuItemLabeled:` message (we can also get the item by specifying its index or the value or selector associated with the item). For example,

```kotlin
menuItem := menu menuItemLabeled: 'One'.
menuItem := menu menuItemAt: 3.
menuItem := menu menuItemWithValue: aValueOrMethodSelector.
```

Here are some of the changes you can make to a menu or a menu item while your application is running.

<table><tr><td>menuItem disable.</td><td>Disable a menu item</td></tr><tr><td>menuItem enable.</td><td>Enable a menu item</td></tr><tr><td>menu hideItem: menuItem.</td><td>Hide a menu item</td></tr><tr><td>menu unhideItem: menuItem.</td><td>Make visible a hidden menu item</td></tr><tr><td>menu backgroundColor: ColorValue green.</td><td>Change the menu color</td></tr><tr><td>(menu menuItemLabeled: 'Three') color: ColorValue red.</td><td>Change the color of a menu item</td></tr><tr><td>menu addItemLabel: 'New Item' value: #someMessageSelector.</td><td>Add a menu item to the end</td></tr><tr><td>menu removeItem: (menu menuItemLabeled: 'New Item').</td><td>Remove a menu item</td></tr></table>

## Creating the menu at selection time

We can dynamically choose the menu to display when the user goes to select a menu item. Before any items are shown, we figure out what the menu should look like and display the newly created menu. To make this work, we install a block of code in the `preBuildWith:` method, rather than creating a method that will return the menu. This block of code will be executed each time the user tries to select the menu. (Note that this technique does not work for menu bars.) An example of this technique can be seen in the class `MenuDynamicCreate` in the file `widgets.st`.

```kotlin
preBuildWith: aBuilder
    aBuilder menuAt: #menuButtonMenu put: [self selectMenu].
    aBuilder menuAt: #inputFieldMenu put: [self selectMenu].
    aBuilder menuAt: #textEditorMenu put: [self selectMenu]
```

```kotlin
selectMenu
    mode == #menuOne
        ifTrue: [^self menuOne]
        ifFalse: [^self menuTwo]
```
<figure><img src="image_47.png" /><figcaption>**Figure 26-4.** Dynamically creating menus.</figcaption></figure>

## Keyboard events and double-clicking

All active widgets (widgets that accept keyboard input) allow you to intercept keystrokes by specifying a block of code as a keyboard hook. List and Table widgets also allow you to specify actions to take when the user double clicks a selection using a mouse. You specify the double click method in the Notification page in the Properties Tool. Alternatively, you can programmatically specify a block of code or a method to invoke, which overrides any method you specified in the Properties Tool.

Let's look at an example using a List box (you can find the code in the file `listdemo.st` on the diskette). Create an application class called `ListDemo` with two instance variables, `list` and `keyboard selectors`.

<figure><img src="image_48.png" /><figcaption>**Figure 26-5.** The ListDemo window.</figcaption></figure>

We'll specify the double-click action in two ways, with a method and a block of code to execute. We'll write code to delete the selected item when the user presses the Delete key, and to show a dialog box when the user presses the right arrow key. To make the keyboard hook general, we'll record the keys and the methods they should invoke in a Dictionary. We set this up during initialization.

```python
ListDemo>>initialize
    pets := SelectionInList new.
    pets list: #('dog' 'cat' 'mouse' 'parrot') asList.
```
self mySetUpKeyboard Selectors

ListDemo>>mySetUpKeyboard Selectors
keyboard Selectors := Dictionary new.
keyboard Selectors
    at: Character del put: #deleteSelection;
    at: #Right put: #expandSelection

Here are the methods that will be executed when the user presses the delete key or the right arrow key.

ListDemo>>deleteSelection
| collection index |
index := self pets selectionIndex.
index > 0 ifTrue: [self pets list removeAtIndex: index]

ListDemo>>expandSelection
self pets selectionIndex > 0
ifTrue: [Dialog warn: 'Details of selection']

Now we want to specify a keyboard hook that will allow us to intercept keystrokes. We'll also specify a block of code that will be executed when the user double clicks on a list selection. We tell the controller about the keyboard hook and the controller's dispatcher about the double-click block or method.

ListDemo>>postBuildWith: aBuilder
| listController |
super postBuildWith: aBuilder.
listController := (self builder componentAt: #petsLB) widget
controller.
listController keyboardHook: self myKeyboardHookBlock.
listController dispatcher doubleClick: [self blockDoubleClick].

A keyboard hook is a block of code taking two parameters, the event and the controller. It should return the keyboard event or nil, nil meaning that no further processing should be done on the keyboard event. We'll always return the event so that the list can do its usual processing. Because we store the actions in a Dictionary, we can change the keystrokes that we are looking at, and the actions they should perform, based on the current context.

ListDemo >myKeyboardHookBlock
^
[:event :controller |
| selector |
selector := keyboard Selectors at: event keyValue ifAbsent: [nil].
selector notNil ifTrue: [self perform: selector].
event]

When the block is executed in response to a double mouse click on a selection, we'll change the double click mechanism to specify a method to be executed rather than a block. Then when the method we specify is invoked, we'll change the mechanism back to using a block.

ListDemo>>blockDoubleClick
Dialog warn: 'Block double click'.
(self builder componentAt: #petsLB)
widget controller dispatcher doubleClickSelector:
#selectorDoubleClick

ListDemo>>selectorDoubleClick
Dialog warn: 'Selector double click'.
(self builder componentAt: #petsLB)
widget controller dispatcher doubleClick: [self
blockDoubleClick].
# Extending the Application Framework

The basic VisualWorks ApplicationModel framework is an excellent way to approach building an application with user interface screens. However, as with most things, it's possible to extend the framework to make the development of user-interface oriented applications easier. In particular, Tim Howard has written extensions to the ApplicationModel framework that he has described in various articles and in a book.

The extensions consist of several new classes: *ExtendedApplicationModel*, *ExtendedSimpleDialog*, *DomainObject*, *DomainAdaptor*, and *CollectionAdaptor*. The code for all these extensions is in the Smalltalk Archives. It's worth spending some time looking into using these extensions in your application.

## Advantages of the extended framework

If you subclass your applications off *ExtendedApplicationModel* rather than *ApplicationModel*, you get a lot of benefits in terms of cleaner and simpler code. Let's look at a few of them here.

### Simpler code

*ExtendedApplicationModel* allows you to do everything you could do with *ApplicationModel*, but makes much of it a lot easier. Here are some examples written first with *ApplicationModel* functionality, and second with *ExtendedApplicationModel* functionality.

#### ApplicationModel

(self builder componentAt: #saveAB) enable.

(self builder componentAt: #editAB) enable.

(self builder componentAt: #cancelAB) disable.

#### ExtendedApplicationModel

self enable: #(saveAB editAB).

self enable: #(saveAB editAB) disable: #cancelAB

#### ApplicationModel

component := self builder componentAt: #employeeNameIF.

widget := (self builder componentAt: #employeeNameIF) widget.
`controller := (self builder componentAt: #employeeNameIF) widget controller.`

### ExtendedApplicationModel

`component := self component: #employeeNameIF.`

`widget := self widget: #employeeNameIF.`

`controller := self controllerFor: #employeeNameIF.`

## Eliminating instance variables

`ApplicationModel` keeps an instance variable for each widget on the screen that will be handling input. Each input field, each list, each table, and so on will require at least one instance variable. However, the builder also keeps track of the data, so the instance variables are actually redundant. `ExtendedApplicationModel` uses the builder's variables, allowing you to write applications without all the usual instance variables. To do this, it provides new methods for creating `ValueHolders` and `SelectionInLists`. Here is an example of an access method using the new functionality.

`colors`

`^self`

`selectionInListFor: #colors`

`collection: self domain colors`

`selectionChange: #colorChanged`

Notice that we are not initializing or returning an instance variable. The code is also smart enough to return the `SelectionInList` if it exists, and to create a new one if it doesn't exist. It also registers as a dependent of the `SelectionInList`, removing the necessity to set up the dependency using `onChangeSend:to:`.

## DomainAdaptors

Recall that in Chapter 23, Model-View-Controller, we noted that the `ApplicationModel` framework provides the concept of a *subject channel* which makes it possible to replace one domain object with another and have all the `AspectAdaptors` now refer to the new object. The `DomainAdaptor` class provides additional mechanisms for associating screens with domain objects. A `DomainAdaptor` is in effect an editor for a single domain object. You can open a `DomainAdaptor` on a domain object, or simply open a `DomainAdaptor`, which creates a new domain object. `DomainAdaptors` allow you to replace a domain object with a new domain object, and they update the data in the views when you do so.

`employeeDA := EmployeeUI open.`

`employeeDA := EmployeeUI openOn: anEmployee.`

`employeeDA domain: anotherEmployee.`
DomainAdaptors make it easy to create AspectAdaptors using no instance variables, and to register for
change messages at the same time. For example,

name

^self aspectAdaptorFor: #name changeMessage: #nameChanged

They also let you edit collections that are part of the domain object. For example, if the employee has a set
of skills that you want to add to or remove from as part of editing employee information, your **skills** method might
look like the following.

skills

^self

collectionAdaptorFor: #skills

addSelector: #addSkill

removeSelector: #removeSkill

changeMessage: #skillSelectionChanged

## Other useful mechanisms

The ExtendedApplicationModel allows you to keep track of your parent application, which gives you the
opportunity to send it messages if necessary. You can open an application as a single instance, which ensures that
only one instance of the application will be created. If you try to open the application again, the single instance will
be expanded or raised if it was collapsed or behind another window. There are extensions to Dialogs, and
applications can be opened either as a Dialog (modal) or as a Application window (non-modal). There are many,
many more features than we've discussed here; this chapter simply touches on the extensions to the
ApplicationModel framework.

## How to get the extended framework

Tim Howard has written articles on his frameworks extensions in several issues of The Smalltalk Report,
and his code is available in the Smalltalk archives (the file *domain.st* contains all the classes mentioned above). For
information about retrieving software from the Smalltalk Archives, see Chapter 35, Public Domain Code and
Information. However, I recommend that you purchase his book, *The Smalltalk Developer's Guide to VisualWorks*.

Tim Howard
The Smalltalk Developer's Guide to VisualWorks
SIGS Books, ISBN 1-884842-11-9.
Prentice Hall, ISBN 0-13-442526-X

The book covers the same material as his articles in The Smalltalk Report plus a lot more. It comes with a diskette containing all the framework extensions and a significant amount of example code. In particular, it contains an excellent tutorial that is run as a Smalltalk application, and which is invaluable in learning the VisualWorks application framework and application widgets, as well as Howard's extensions to the framework. To me, the tutorial itself is easily worth the price of the book.
28

Eliminating Procedural Code

In procedural programming, we write a lot of code that gets information then makes a decision based on the information. In C, we see a lot of `if/else if/else` blocks, and a lot of `switch` statements. If we wrote the same type of code in Smalltalk we might see the following.

```java
MyClass>>myDoLoop
    [self myProcessObject: self myObject] repeat

MyClass>>myProcessObject: anObject
    anObject isSuccessResponse
        ifTrue: [^self myProcessSuccess: anObject].
    anObject isFailureResponse
        ifTrue: [^self myProcessFailure: anObject].
    anObject isHeartbeat
        ifTrue: [^self myProcessHeartbeat: anObject].
    self myProcessUnknown: anObject
```

The trouble is that this code demonstrates procedural thinking. In fact, if you start writing code like this, the logical conclusion is “why is there no `switch` statement in Smalltalk?” At one time, we wrote a `Switch` class, but each time we used it we got into trouble. Eventually we realized that while a `switch` statement was seductive, it caused us to think procedurally and our objects got messed up. We finally removed the class and rewrote all the code that used it.

Tell, don't ask

How might we write the above code if we use the OO *tell, don't ask* approach. The classic solution is use polymorphism, to simply tell the object to process itself, and rely on each type of object being able to do this in its own way. Give the object responsibility and make it responsible for carrying out the action. For example,

```java
MyClass>>myProcessObject: anObject
    anObject processYourself
```
Sometimes, however, this approach doesn't work because some or most of the behavior and knowledge is in
MyClass. If the work will be shared between MyClass and the object it is processing, we can give the objects
knowledge of each other. For example,

MyClass>>myProcessObject: anObject
anObject processYourselfWith: self

OtherClass>>processYourselfWith: anObject.
self myDoSomeStuff.
anObject doSomeStuffWith: self.
self myDoMore Stuff

MyClass>>doSomeStuffWith: anObject
...

If all the work will be done in MyClass, we need a mechanism to figure out what method in MyClass to
execute. The classic answer to this problem is double dispatching, where the first object tells the second object
tell the first object what to do. In our example, MyClass doesn't know what method to execute, so it tells the
other object to tell it what method to execute.

MyClass>>myProcessObject: anObject
anObject processUsing: self

Then in each class that the object could belong to, we see the following.

SuccessResponse>>processUsing: anObject.
anObject processSuccessResponse: self

FailureResponse>>processUsing: anObject.
anObject processFailureResponse: self

Heartbeat>>processUsing: anObject.
anObject processHeartbeat: self

We also add processUsing: to Object to trap all the situations where we come across an object that
doesn't understand processUsing:. Ie, an object for which we haven't yet written processUsing:.

Object>>processUsing: anObject
anObject processUnknown: self.

Back in MyClass, we implement the code that knows how to handle the different types of objects we might
be processing.

MyClass>>processSuccess: anObject
.. do success stuff ..

MyClass>>processFailure: anObject
.. do failure stuff ..

MyClass>>processHeartbeat: anObject
.. do heartbeat stuff ..

We also add processUnknown: to handle those situations where the other object inherited
processUsing: from Object. Ie, where we forgot to write processUsing:.
MyClass>>processUnknown: anObject
    self error: anObject printString,
    ' does not understand processUsing:'.

## Processing external objects

Another type of object we may need to deal with is an object we get from an outside source such as a socket or a serial line. For example, we might be talking with an external device and getting back status codes. Or we might be getting requests sent in over sockets, each request telling the program to do something different.

Typically we will get information in the form of a string and we'll have to figure out what to do based on the contents of the string. An obvious procedural answer is to compare the data with known strings and do different things for different data. However, we want an OO answer, so let's look at ways to deal with this type of object without having to make explicit decisions.

### perform:

One way is to use one of the perform: family of messages. When you write a Smalltalk method, you usually specify all the messages that it will send. So, although the arguments won't be known until runtime, all the message names are known at compile time (when you accept the method). The perform: family of messages give us the ability to create a symbol and use this symbol as a message name. By using perform:, we don't have to specify the message names when we write the method and can delay this knowledge until runtime. The perform: family has several members, depending on how many keywords there are in the message to be performed. For each keyword, you need one argument.

self perform: selector.
self perform: selector with: argument.
self perform: selector with: argument1 with: argument2.
self perform: selector with: argument1 with: argument2 with: argument3.
self perform: selector withArguments: argumentArray.

Suppose that from an external device we get back status codes as numeric strings, and we take different actions for different status codes. We could prefix the code with a string, then perform this as a method. For example:

MyInterface>>handleResponse
   reatingResponse.
   here: (msg, response)
    selector := ('msg', response asSymbol).
    self perform: selector.

In a production system you would pass in additional information to the performed method, so let's assume that we get back a status code followed by a space followed by some real data.

MyInterface>>handleResponse
    response := self myDeviceResponse.
    selector := ('msg', (response copyUpTo: Character space))
    asSymbol.
    self perform: selector with: response.
Instead of having meaningless methods such as `msg0215`, let's keep a dictionary of message selectors (alternatively, you could keep a dictionary of code blocks). The relationship between status codes and selectors could be set up in the class side `initialize` method, storing the relationships in an instance of `Dictionary`. We may have to take the same action for several status codes so this technique has the added benefit that we don't have to write several methods to do the same thing.

```kotlin
MyInterface class>>initialize
    "self initialize"
    StatusCodeDictionary := Dictionary new.
    StatusCodeDictionary
        at: '0215' put: #performDeviceOffline;
        at: '0216' put: #performInvalidParameters
```

```kotlin
MyInterface>>myStatusSelector: aString
    ^StatusCodeDictionary
        at: aString
        ifAbsent: [#performUnknownStatusCode]
```

```kotlin
MyInterface>>handleResponse
    response := self myDeviceResponse.
    selector := self myStatusSelector: (response copyUpTo: Character
        space).
    self perform: selector with: response.
```

Notice that we've prefixed the method names in the dictionary with `perform`. A drawback to performing methods is that if the method name is created programatically, there will be no references to the method. If you run Class Reports (a tool in the Advanced Tools that offers some lint-like capabilities), it will tell you that the method is implemented but not sent. Unsent messages are always candidates for removal, so having a distinct prefix for performed methods reduces that likelihood that you will unknowingly remove methods that are needed.

## Dictionary of classes

The technique shown above can be useful when we get some data and want to execute different methods based on the data. Sometimes, however, we will want to create a new object and have the object do the processing. For example, from a socket we get a string representing a request and the various request parameters. We want to create a request object of the right type then tell the request object to process itself.

One approach is to have a set of request classes, with a superclass of `MyRequest`. On the class side, `MyRequest` has a dictionary containing relationships between strings and class names. To create a request object, we ask the superclass, `MyRequest`, to create the appropriate type of request. An instance of `InvalidRequest` is created if the string does not correspond to a valid request type. This `InvalidRequest` should respond with error information when sent the message `processYourself`.

```kotlin
MyInterface>>handleRequest
    input := self mySocketInput.
    request := MyRequest newFrom: input.
    request processYourself
```

```kotlin
MyRequest class>>newFrom: aString
    requestType := aString copyUpTo: Character space.
    requestClass := RequestDictionary
```
```
at: type
ifAbsent: [#InvalidRequest].
^requestClass new initialize: aString.
```

The dictionary could be built explicitly as in the previous example. However, this has the disadvantage that every time you add a new request class, you have to remember to update the `RequestDictionary`. You're taking responsibility away from the objects themselves and putting it somewhere else.

Another approach is for each request class to know the string that is associated with it. In `MyRequest` we write an initialization method, `initializeRequests`, which asks all the subclasses of `MyRequest` for their string. Depending on whether you fileIn your code or keep it in the image, you could have `initialize` send `initializeRequests` or you could do `MyRequest initializeRequests` during product startup.

```FLASH
MyRequest class>>initializeRequests
"self initializeRequests"
RequestDictionary := Dictionary new.
self allSubclassesDo:
    [:each | each requestName notNil
     ifTrue: [RequestDictionary
             at: each requestName
             put: each]]
```

```FLASH
MyRequest class>>requestName
"Don't inherit the name. Make sure the request explicitly
implies it"
^(self class includesSelector: #myName)
    ifTrue: [self myName]
    ifFalse: [nil]
```

```FLASH
SomeRequestSubclass class>>myName
^'register'
```

We don't want a request class to inherit its request name from a superclass, so we have code to handle classes that don't implement `myName`. We simply don't put them in the dictionary. If we get a string for which there is no entry in the dictionary, the code in `newFrom:` returns the `InvalidRequest` class, which generates the appropriate error code when instantiated and sent the `processYourself` message.

## Summary

To eliminate procedural code we should *tell rather than ask*. Ideally we use polymorphism and simply tell the object to process itself in some way. We may have to split the responsibility, in which case we may tell the object to process itself using us. Or we may use *double dispatching* to avoid a pseudo switch statement. With certain types of object we can use the `perform:` family of messages, or we can build dictionaries that store relationships between classes and another object such as a string or a symbol.
# 29

# Meta-Programming

In Smalltalk, we usually write code that creates objects then makes the objects interact by sending each other messages. Sometimes, however, you will want to do a different type of programming, one that makes use of the internal structure of classes and objects. You may want to find out what variables a class defines, what methods it implements, or whether it defines a particular protocol. You may want to do some operation for each subclass of a class. This type of programming is called meta-programming.

Meta programming is not for the faint of heart or for the inexperienced. However, as you become more comfortable with Smalltalk, you may find it useful to know something about how things are done behind the scenes. The main classes to look at are *Behavior*, *ClassDescription*, *Class*, and *Metaclass*, all of which reside in the Kernel-Classes category. We'll talk a little about how these classes interact, but for a fuller description see the Purple Book (Smalltalk-80, *The Language*, by Adele Goldberg and David Robson, Addison-Wesley).

## Classes and Metaclasses

Let's start by taking a look at classes and their metaclasses. Just as an *OrderedCollection* is an instance of the class *OrderedCollection*, the class *OrderedCollection* is an instance of another class. A class whose instances are classes is called a *metaclass*, so *OrderedCollection* is an instance of its metaclass. When you define a new class, a new metaclass is automatically created for it — the metaclass has exactly one instance, the class you created. The metaclass is an instance of the class *MetaClass* and it has no name, so you can't look at it in a Browser. If you inspect the two statements below that were evaluated in a plain VisualWorks 2.5 image, you'll see that the number of subclasses of *Object* is about twice the number of class names in Smalltalk<fnref n="1" />. This illustrates the point that each class has a unique metaclass.

<table><tr><td>Object allSubclasses size.</td><td>1903</td></tr><tr><td>Smalltalk classNames size.</td><td>960</td></tr></table>

<footnote n="1">¹ The first number is not exactly twice the second since there are a few classes that are not subclassed off Object. Also, the number of subclasses of *Object* is an odd number because *Metaclass* is a strange oddity, having a metaclass of *Metaclass*.</footnote>
Since a class is an instance of its metaclass, what we think of as class side methods are really instance side methods of the class's metaclass. Every class has an instance variable, *methodDict*, that stores the methods that have been defined by the class for invocation by instances of the class. So in the *methodDict* variable of a class's metaclass are stored the methods that have been defined on the metaclass for invocation by its instances — in this case the single instance which is the class. Thus all methods are really instance methods. To see a concrete example for yourself, inspect *OrderedCollection* and look at the *methodDict* variable. This shows all the instance side methods of *OrderedCollection*. Now inspect *OrderedCollection class* and look at *methodDict*. You will see the class side methods of *OrderedCollection*. Figure 29-1 shows the two inspectors.

<figure><img src="image_49.png" /><figcaption>Figure 29-1. The methods of a class and its metaclass.</figcaption></figure>

So, if you send `initialize` to an instance of a class, you are invoking the instance method of the class. If you send `initialize` to the class, you are invoking the instance method of the class's metaclass. For example, to count the number of methods defined for `OrderedCollection` on both the instance and class side, you can do the following. This counts the number of methods defined by `OrderedCollection` plus the number of methods defined by `OrderedCollection`'s metaclass.

`OrderedCollection selectors size + OrderedCollection class selectors size.`

Because class side methods are actually defined on the class's metaclass, the notation for class side methods of `MyClass class>>myClassMethod` is more than just a notation convention. It actually correctly describes the structure since `MyClass class` returns the metaclass.

Just as instance side methods are defined by the class and class side methods are defined by the metaclass, instance variables are defined by the class, and class instance variables are defined by the metaclass. A class has a variable named *instanceVariables*, in which are stored the names of the instance variables of the class's instances. Similarly, the class's metaclass stores the names of the instance variables of its instances — ie, of the class itself. To make all this talk of method dictionaries and instance variables clearer, take a look at the code in the file `metademo.st`. Figure 29-2 shows inspectors looking at instance variables of a class and its metaclass where the class has defined instance, class, and class instance variables.
<figure><img src="image_50.png" /><figcaption>Figure 29-2. Instance variables of a class and its metaclass.</figcaption></figure>

## Adding general class side behavior

In chapter 32, Changes to System Classes, we will see examples of adding general instance side behavior to Object so that all instances inherit the behavior. In this section we will look at adding general class side behavior that is inherited by all classes. The obvious place to add general class methods is the class side of Object. However, if you look at the class side methods of Object you will see that there are very few of them, and that most of them are associated with the signals that Object keeps in its class variables. Methods such as new and new: are conspicuously absent. So if methods associated with class side behavior of subclasses is not found in Object, where are they found?

Just as instances execute methods defined either on their class or a superclass of their class, classes execute methods defined either on their metaclass or a superclass of their metaclass. So if you want a class side method that all classes will inherit, you can either write it on the class side of Object (where it is implemented on Object's metaclass), or on the instance side of one of the superclasses of Object's metaclass.

The superclass of Object's metaclass is *Class* — ie, *Object class superclass* is *Class*. Class has a superclass of *ClassDescription*, which has a superclass of *Behavior*. So to add general class side behavior, we can add it to the class side of Object or we can add it to the instance side of Class, *ClassDescription*, or *Behavior*. Both *Class* and *ClassDescription* are associated with the internal workings of classes and instances, with the handling of classes, variables, protocols, etc. *Behavior* provides additional behavior and is where *new* and *new*: are defined. The class comment for *Behavior* includes the following: "Most objects are created as instances of the more fully supported subclass, *Class*, but *Behavior* is a good starting point for providing instance-specific behavior." Thus, based on the purpose of these three classes, the instance side of *Behavior* is the most appropriate place to add general class side methods.

As an interesting note, the superclass of *Behavior* is *Object*. So, to add new class side behavior, we could actually add the method to the *instance* side of *Object*. We can demonstrate this by sending a method defined on the instance side of *Object* to a *Class* (for example, *OrderedCollection basicSize*). Try the following. Define the method *foo* on the instance side of *Object*, then send it to the class *OrderedCollection* and to an instance of *OrderedCollection*.

OrderedCollection new foo.
OrderedCollection foo.
```
Object>>foo
Transcript cr; show: thisContext printString.
```

Of course, the problem with defining new class side behavior on the instance side of Object is that it will be inherited by both instances and classes, which is not what we want. Figure 29-2 illustrates the parallel instance and class side hierarchy.

<figure><img src="image_51.png" /><figcaption>**Figure 29-3.**
The instance and class side hierarchy.</figcaption></figure>

## Examples we've seen in other chapters

We've seen examples of meta-programming in other chapters. For example, in Chapter 15, Printing Objects, we wrote `printAllOn:` using the messages `allInstVarNames`, `instVarIndexFor:` and `instVarAt:` to find the names and values of instance variables. In Chapter 30, Testing, we send the message `includesSelector:` to find out if a particular message selector is defined by a specified class. In the same chapter we send the messages `organization` and `listAtCategoryNamed:` to get the names of all the methods in a specified method protocol. In Chapter 33, Managing Source Code, we show how to count the number of classes and methods in the image using the `classNames` and ` selectors `messages.

## Examples we promised in other chapters

### Finding classes with a specified protocol

In Chapter 20, Error Handling, we mentioned that we would write code to find all the classes that contain a specified protocol. If you follow the convention mentioned in Chapter 32, Changes to System Classes, you will put additions to system classes in a protocol named (`additions`). When we get a new release of VisualWorks, we may need to find all the system classes to which we've added methods, so let's write our code to look for all classes that include the protocol (`additions`).

```
Object allSubclasses select:
    [:each | each organization categories includes: #'(additions)'].
```
The above example finds all the classes that contain the `(additions)` protocol on either the class or instance side. It works because the subclasses of `Object` include both the regular classes and also their metaclasses. If we just wanted to find the classes that include the protocol on the class side we would look only at metaclasses, as in the example below. (Correspondingly, to find classes that include the protocol on the instance side we would replace `each isMeta` with `each isMeta not`.)

```clojure
Object allSubclasses select:
  [:each | each isMeta and: [
    each organization categories includes: #'(additions)]]
```

The top-level classes in `Smalltalk` have `nil` as their superclass, with `Object` being the main top-level class. To find all the classes that have `nil` as their superclass, inspect `Class rootsOfTheWorld`. If you want to see all the classes that include the `(additions)` protocol, including `Object` and other class hierarchies that are subclassed off `nil`, do the following.

```clojure
collection := OrderedCollection new.
Smalltalk allBehaviorsDo:
  [:each | (each organization categories includes: #'(additions)')
    ifTrue: [collection add: each]].
collection inspect.
```

The `Browser` makes heavy use of meta-programming, and you can find some interesting methods on its class side. For example, to find the names of all the methods in all the `class` side (`additions`) protocols, inspect the first example. To browse all the methods in these protocols, do the second example.

```clojure
Browser allClassMethodsInProtocol: #'(additions)'.
Browser browseAllClassMethodsInProtocol: #'(additions)'.
```

To look at all methods rather than just class side methods, create a new method, `allMethodsInProtocol:`, which tells you all the classes with the specified protocol, regardless of whether the protocol appears on the class side or the instance side. Base the new method on `allClassMethodsInProtocol`: but remove the `isMeta` test. Also create a new method, `browseAllMethodsInProtocol:`, basing it on `browseAllClassMethodsInProtocol:`, but sending the `allMethodsInProtocol:` message instead of `allClassMethodsInProtocol`. You can now browse all your additions to system classes by doing the following.

```clojure
Browser browseAllMethodsInProtocol: #'(additions)'.
```

## allInstancesAndSubInstances

In Chapter 16, Processes, we mentioned that if you subclass off `Process`, you will need to modify code reading `Process allInstances` to now read `Process allInstancesAndSubInstances`. Here's the definition of this new method. Note the `yourself` in the `into:` block which guarantees that the block value is the collection that will be injected in the next iteration.

```clojure
Behavior>>allInstancesAndSubInstances
  ^self withAllSubclasses
    inject: OrderedCollection new
```
```
into: [:coll :each | coll addAll: each allInstances;
yourself]
```

## Creating accessors for instance variables

In Chapter 3, Methods, and Chapter 4, Variables, we mentioned that we would write code to automatically create accessors for our instance variables. To do this we add the following methods to *Class*. This mechanism will create public and private (`my` prefixes) accessors for each instance variable. You can then remove the ones that you don't need. To save space, we only show two of the methods that return the string used to create the accessing methods, and have compressed cascades and other messages. We also make use of the `capitalize` method we wrote in Chapter 12, Strings.

```
Class>>mySubclass: t instanceVariableNames: f classVariableNames: d
poolDictionaries: s category: cat
| newClass |
newClass := self
    subclass: t instanceVariableNames: f classVariableNames: d
    poolDictionaries: s category: cat.
newClass instVarNames do:
    [:each |
    newClass compile: (self getAccessor: each) classified:
        #accessing.
    newClass compile: (self setAccessor: each) classified:
        #accessing.
    newClass compile: (self myGetAccessor: each) classified:
        '#private-accessing'.
    newClass compile: (self mySetAccessor: each) classified:
        '#private-accessing'].
    ^newClass
```

```
Class>>getAccessor: aName
| stream |
stream := String new writeStream.
stream nextPutAll: aName.
^self getAccessor: aName stream: stream
```

```
Class>>mySetAccessor: aName
| stream |
stream := String new writeStream.
stream nextPutAll: 'my'.
stream nextPutAll: aName capitalize.
^self setAccessor: aName stream: stream
```

```
Class>>getAccessor: aVariableName stream: aStream
    ^aStream crtab; nextPut: $^; nextPutAll: aVariableName;
    contents
```

```
Class>>setAccessor: aVariableName stream: aStream
| value prefix |
value := aVariableName capitalize.
prefix := (value at: 1) isVowel ifTrue: ['an'] ifFalse: ['a'].
value := prefix, value.
^aStream
nextPutAll: ': '; nextPutAll: value; crtab; nextPutAll:
aVariableName;
    nextPutAll: ' := '; nextPutAll: value; contents
```
To use this mechanism, when you define a new class, replace the `subclass:` keyword with `mySubclass:`. When you accept the class definition, the new protocols will be created and public and private accessors will be created for every instance variable. For example, the first two lines of the class definition might look something like the code shown below. Following is an example of one of the accessors that was created for `age`.

```kotlin
Object mySubclass: Person
instanceVariableNames: 'name age address '

Person>>myAge: anAge
age := anAge
```

## A brief overview of other capabilities

There are a wealth of methods that do interesting things. You can find all the immediate subclasses of a class (`subclasses`), the whole hierarchy of subclasses (`allSubclasses`), the class itself with all its subclass hierarchy (`withAllSubclasses`), and the corresponding superclass methods (`superclass`, `allSuperclasses`, and `withAllSuperclasses`).

You can see if a class is identically equal to another class or is a subclass of it (`includesBehavior:`), if it is simply a subclass (`inheritsFrom:`), or if it is an immediate subclass (`isDirectSubclassOf:`).

You can look at all the instances of a particular class (`allInstances`), all the objects that reference a particular object (`allOwners` and `allOwnersWeakly:`). (If you do either of these, you might want to do `ObjectMemory garbageCollect` beforehand, to eliminate any unused objects that are waiting to be garbage collected.) You can iterate over all the subclasses of a class (`allSubclassesDo:`), all the instances of a class (`allInstancesDo:`), and all the instances of a class's subclasses (`allSubInstancesDo:`).

You can look at all the methods a class defines (` selectors `), and all the methods it understands, including inherited methods (`all selectors `). You can see if an object understands a particular message (`respondsTo:`) and whether a particular method is defined by a class (`includesSelector:`). You can even find which class in the hierarchy defines a method that your object responds to (`whichClassIncludesSelector:`).

You can look at all the instance variable names defined by a class (`instVarNames`), all the instance variable names that it both defines and inherits (`allInstVarNames`), and similarly for class variable names. You can find the number of instance variables (`instSize`), the index for a particular instance variable name (`instVarIndexFor:`) and the value of an instance variable for a given index (`instVarAt:`).

Tread lightly when doing programming that involves knowledge of class structure. It can be useful, but should not be used as a substitute for good application design.
30
Testing

It seems easier to write error free code in Smalltalk than in other languages. I suspect that this is partly because it's difficult to have off-by-one errors, the garbage collector takes care of memory management, there is a very rich class library, and there are no pointers. However, we still do create errors, both coding errors and functionality errors — ie, we didn't code the correct functionality. So we need to test the software. Smalltalk code is easy to test and debug because it is so interactive. However, as with any other language, once we've done our initial development and testing, it is psychologically difficult to thoroughly retest after making changes. What we need is way to develop test cases that can be retained and replayed after changes.

In this chapter we will look at a way to develop tests, and a user interface to run the tests. I want to acknowledge Kent Beck and his article, *Simple Smalltalk Testing* (The Smalltalk Report, October 1994), for presenting some interesting ideas that I used in developing the testing scheme that follows. This chapter contains a lot of code. If you work through it then by the end of the chapter you should have a working test facility. Hopefully you will also have learned some useful ideas for other problems you are working on. As in other chapters, to save on space I won't generally use accessors for instance variables and the formatting is sometimes tighter than usual. The code can also be found in the file `testing.st`.

The testing scheme here is not designed to test user interfaces. There are specialist products available to capture and replay keystrokes and mouse actions. A good application will separate out the user interface from the domain model, and it should be possible to test the domain model in isolation from the user interface. This is where the classes described in this chapter can help. The scheme described uses a test manager to runs tests. Rather than embed the tests within the classes that we want to test, we have separate test classes that exist in a well-defined hierarchy. The test manager makes use of this hierarchy when figuring out which tests to run.

The Test class

The basic concept is that we have a *TstTest* class (Tst is the prefix I am using for my testing classes) that provides the behavior for running test cases. We organize our tests by subclassing off TstTest. Each test class can have both individual tests to run, and subclasses that have their own individual tests and their own subclasses.

Copyright © 1997 by Alec Sharp

Download more free Smalltalk-Books at:

- The University of Berne: http://www.iam.unibe.ch/~ducasse/WebPages/FreeBooks.html

- European Smalltalk Users Group: http://www.esug.org
This hierarchy mechanism gives us a way to organize our tests in some logical fashion. For example, you
might have the immediate subclasses of TstTest be ProductTests, SupportClassTests, and MyTests. Subclassed
off ProductTests you might have SystemTests and ComponentTests. Under MyTests could be tests that you have
written in conjunction with new code you are developing. When you are satisfied with the code and have
officially blessed it, you might move the tests you wrote into the ProductTests or SupportClassTests hierarchy.
Figure 30-1 illustrates the hierarchy.

<figure><img src="image_52.png" /><figcaption>**Figure 30-1.**
The TstTest class hierarchy.</figcaption></figure>

We run the tests using a test manager that organizes the test classes by their inheritance hierarchy. There are two ways to run tests. The first way runs a hierarchy of tests and reports on the results in a *TstResult*. The second way runs individually selected tests and raises an exception when a failure occurs, allowing you to go into the debugger and look at the values.

Building the TstTest class

Object subclass: #TstTest
instanceVariableNames: 'selector '
classVariableNames: 'TestFailedSignal '
poolDictionaries: ''
category: 'TST-Test'

TstTest class
instanceVariableNames: 'DisplayName '

If a test fails, our code raises a TestFailedSignal. Rather than create a signal for each test, we create it for the
class, which means we need a class initialization method. In this method we also set the name to be displayed by
the Test Manager.

TstTest class>>initialize
"self initialize"
DisplayName := 'All Tests'.
TestFailedSignal := (self errorSignal newSignal)
  notifierString: 'Test failed: ';
  nameClass: self message: #testFailedSignal;
  yourself

TstTest class>>testFailedSignal
^TestFailedSignal
We don't really need to send the `nameClass:message:` message when creating the signal, but it's good practice to include it when creating a signal because it allows other methods to create their own instance of a `TestFailedSignal`.

The general idea is that a subclass of `TstTest` can have its own subclass hierarchy and some individual tests to run. The test manager will find all the individual tests for a given test class, and create an instance of the class for each test to run. The individual tests each have their own method name in the `tests` protocol. So when an instance is created, the method selector to run is specified.

```kotlin
TstTest class>>newTest: aSelector
    ^self new initialize: aSelector

TstTest>>initialize: aSelector
    selector := aSelector

TstTest>>printOn: aStream
    aStream
        print: self class;
        nextPutAll: '>>';
        print: selector
```

What does an individual test look like? Below is an example of one. Notice that it does some work, then sends the `expect: string:` message. This tells the test code that it expects the code in the block to evaluate to `true`. If the code evaluates to `false`, the test fails. The string that is sent as a parameter is simply a way of making it easier to find the part of the test that failed. If you only have one result, you can do `self expect: [some code]`.

```kotlin
SomeTest>>driveBusy
    | request response |
    request := self myMountRequest: 'PAYROLL' drive: 'DRIVE2'.
    response := self mySendMessage: request.
    self expect: [response isSuccessResponse] string: 'Mount first volume'.
    request := self myMountRequest: 'BKUP950524' drive: 'DRIVE2'.
    response := self mySendMessage: request.
    self expect: [response isFailureResponse] string: 'Mount second volume'
```

Let's take a look at what `expect:` and `expect: string:` do.

```kotlin
TstTest>>expect: aBlock
    self expect: aBlock string: nil

TstTest>>expect: aBlock string: aStringOrNil
    aBlock value ifFalse:
        [self class testFailedSignal raiseErrorString: aStringOrNil]
```

If the block evaluates to `false`, we ask our `TestFailedSignal` to raise an exception. If we specified a string, then it raises the exception using our string as the error string. I'm not going to show them, but you can write the corresponding `reject:` and `reject: string:` methods that reject the result — ie, raise the exception if the block evaluates to `true`.
Now we need to see how the exception is handled. To do this we look at how the tests are run. Remember that we specified the selector (or method) to run when we created the instance of the test and stored the selector in an instance variable. To run the method, we have to perform the selector.

```kotlin
TstTest>>performTest
    self perform: selector
```

We have two ways of performing the test. We can send the `run` message or the `run`: message to the test instance. If we send `run`, there is no exception handling and if a test fails, the exception will raise a notifier window, allowing us to immediately debug the code that failed. If we send `run:`, we specify a test result object in which we will record information about the test.

```kotlin
TstTest>>run
    self performTest

TstTest>>run: aTestResult
    self errorSignal
        handle: [:ex | aTestResult error: ex localErrorString in: self]
        do: [self class testFailedSignal
              handle: [:ex | aTestResult failure: ex localErrorString in:
self]
              do:
                  [aTestResult incrementCount.
                   self performTest]]
```

There are two things that can go wrong with a test: a *failure*, where the result is different from what we expected, and an *error*, where there is an error in the test (for example, the test might send a message that is not understood). We trap both conditions in the `run:` method.

The innermost exception handler looks specifically for TestFailedSignal exception that we raise if we get an unexpected result. If it comes across one, in the `handle:` block it logs the *failure* in the test result. The outermost exception handler traps all exceptions other than those raised by TestFailedSignal. So if we send a not understood message, or do a division by zero, or try to access a non-existent array element, they will all be handled in the `handle:` block, which logs the *error* in the test result.

Finally, on the class side, we write several methods that will be used when interacting with the test manager. The first method specifies the protocol that contains all the individual test case selectors. The second method uses meta-programming to return the names of all the individual test cases in sorted order, and the third method returns the actual test cases.

```kotlin
TstTest class>>testProtocol
    ^#tests

TstTest class>>individualTestNames
    ^ (self organization listAtCategoryNamed: self testProtocol)
    asSortedCollection

TstTest class>>individualTests
    ^self individualTestNames
        collect: [:each | self newTest: each]
```

The next two methods are used to return a collection of the test superclasses of the test that has been selected to run. This collection will be used for doing setup and cleanup work prior to and after running the test.
```java
TstTest class >> rootTestClass
    ^TstTest

TstTest class >> testSuperclasses
    "Returns a collection of the superclasses up to the root test
class"
    | collection class |
    collection := OrderedCollection new.
    class := self.
    [class == self rootTestClass]
    while False:
        [class := class superclass.
         collection add: class].
    ^collection
```

## The Test Result

The test result is the object that stores information about the errors and failures.

```java
Object subclass: #TstResult
    instanceVariableNames: 'test startTime stopTime count failures
errors '
    classVariableNames: ''
    poolDictionaries: ''
    category: 'TST-Test'

TstResult class >> newFor: aTest
    ^super new initialize: aTest

TstResult >> initialize: aTest
    test := aTest.
    count := 0.
    failures := OrderedCollection new.
    errors := OrderedCollection new

TstResult >> incrementCount
    count := count + 1
```

The `failure:`in: method below stores the test case and string in the failure collection. There is an equivalent (but not shown) method for `error:`in: . Since there are only two parameters, the test case and the string, we store them in an Association. If we ever wanted to record more than two pieces of information, we would create a new class.

```java
TstResult >> failure: aString in: aTestCase
    failures add: aTestCase -> aString

TstResult >> start
    startTime := Timestamp now
```

There is a corresponding stop method. The final thing is to provide a `printOn:` method for TstResult. Figure 30-2 shows how a test result might appear when displayed in an inspector window. Following the figure is the code that generates the output.
<figure><img src="image_53.png" /><figcaption>Figure 30-2. The output of a test result.</figcaption></figure>

```
TstResult>>printOn: aStream
aStream nextPutAll: 'Name: '.
test printOn: aStream.
aStream
    cr; nextPutAll: 'Tests run: '; print: count;
    cr; nextPutAll: 'Start time: '; print:startTime;
    cr; nextPutAll: 'Stop time: '; print: stopTime.
self myPrintFailuresOn: aStream.
self myPrintErrorsOn: aStream

TstResult>>myPrintFailuresOn: aStream
failures empty ifFalse:
    [self
        myPrintCollection: failures
        label: 'Failures'
        on: aStream]

TstResult>>myPrintCollection: aCollection label: aString on: aStream
aStream
    cr; cr;
    nextPutAll: aString;
    nextPutAll: ': ';
    print: aCollection size.
aCollection do:
    [:each |
        aStream cr.
        each key printOn: aStream.
        each value notNil
        ifTrue:
            [aStream nextPutAll: ' ('.
                aStream nextPutAll: each value.
                aStream nextPut: $)]]
```
## The Test Manager

Now that we have the test class, let's look at how we might create a user interface to run the tests. First, create a window with a read-only input field, three action buttons, a check box, and two list widgets. Figure 30-3 shows the window.

<figure><img src="image_54.png" /><figcaption>Figure 30-3. The Test Manager.</figcaption></figure>

The read-only input field at the top left displays the currently selected test. To the right is another window showing all the immediate subtests of the current test. Below is a pane showing all the individual tests associated with the current test. There are three action buttons: Run Tests, which runs the hierarchy of tests from the displayed test down; Up a Level, which makes the next higher test in the hierarchy the current test; and Run, which runs the tests that have been selected in the Individual Test pane. Below are the class definition and `initialize` method. In the `aspects` protocol we also need to write methods to get the instance variables (we won't show the getters here).

```python
ApplicationModel subclass: #TstTestManager
    instanceVariableNames: 'mainTest subTestList individualTestList
    doSetup Cleanup '
    classVariableNames: ''
    poolDictionaries: ''
    category: 'STBE-Testing'
```

```python
TstTestManager>>rootTestClass
    ^TstTest
```

```python
TstTestManager>>initialize
    mainTest := self rootTestClass asValue.
    doSetup Cleanup := false asValue.
    subTestList := SelectionInList new.
    subTestList selectionIndexHolder ONChangeSend: #changedSubTest to:
    self.
    individualTestList := MultiSelectionInList new.
```
self myBuildLists.

Let's take a look at what we are doing in the `initialize` method. First, we set our main test from the root test class. Next we set our `subTestList` variable to be a `SelectionInList` and we register the Test Manager as a dependent of the `SelectionInList`, asking to be sent the `changedSubTest` message if the user selects or deselects a test in the right hand pane. Finally, we initialize the individual test list to be a `MultiSelectionInList`, which allows the user to select multiple individual test cases to run. Finally, after setting up the variables, we build the subtest and individual test lists for the current main test.

In the `initialize` method we told the `SelectionInList` object to send us a message if the selection index changes. Here's what we do in the `changeSubTest` method. If the user selected a test in the right hand pane, we want to make it the main test then display its sub-tests and its individual tests, if any.

```python
TstTestManager>>changedSubTest
    self subTestList selection notNil
    ifTrue:
        [self mainTest value: self subTestList selection.
         self myBuildLists]
```

If the user wants to go back up a level in the test hierarchy and presses the Up a Level button, we execute the method `showSuperclass`, which sets the main test to be the superclass of the current test (unless we are already at the root test class), and rebuilds the subtest and individual test lists.

```python
TstTestManager>>showSuperclass
| mainTestClass |
mainTestClass := self mainTest value.
mainTestClass == self rootTestClass
    ifFalse:
        [self mainTest value: mainTestClass superclass.
         self myBuildLists]
```

We've now seen several references to `myBuildLists`, so let's take a look at the method.

```python
TstTestManager>>myBuildLists
| test |
test := self mainTest value.
self subTestList list: test subclasses asSortedCollection.
self individualTestList list: test individualTestNames
```

There are several points to note when looking at this method. When we create the list of subtests, we want to display the subtests in alphabetic order, so we send the `asSortedCollection` message to the collection. For this to work, we need to make sure that our test case classes respond to the `<=>` message which is used to sort a collection.

```python
TstTest class>> <= anObject
    ^self displayString <= anObject displayString
```

```python
TstTest class>>displayString
    ^DisplayName notNil
        ifTrue: [DisplayName]
        ifFalse: [self name]
```

```python
ProductTests class>>initialize
    "self initialize"
```
super initialize.
DisplayName := 'Product Tests'

Note that these methods are all written on the class side since we are displaying classes in the input field and in the subtest list. The `displayString` message is sent to an object by a `SelectionInList` and by an `Input field` (for the input field to work, in the Properties Tool you must define it as holding an Object). We override the default `displayString` to return the display name, assuming that the `DisplayName` class instance variable has been set in the class. This allows us to display something more reasonable than the class name. If we haven't set the `DisplayName`, the class name will be displayed instead. The third method shows here gives an example of how a class would set its `DisplayName`.

# Running Tests

## All Tests

When you press the Run Tests button, you run all the individual tests associated with the displayed test, then recursively go through the sub-tests, running all the individual tests associated with each sub-test and all their sub-tests. The action associated with the Run Tests button is the `runTests` method.

```kts
TstTestManager>>runTests
| testClass  testResult |
testClass := self mainTest value.
testResult := self myTestResultFor: testClass.
self myDoHierarchySetupFor: testClass.
testResult start.
self myRunTestsForClass: testClass result: testResult.
testResult stop.
self myDoHierarchy CleanupFor: testClass.
testResult inspect.
```

We start by creating a test result which we use to record the results of the tests. The code to return a test result is shown here.

```kts
TstResult>>myTestResultFor: aTest
^TstResult newFor: aTest
```

We then do any setup for higher level classes, run the test hierarchy, and do any cleanup for higher level classes. Each test class in the hierarchy can do setup before and cleanup after running the tests. This allows the classes to set up any conditions that are required for the test. Typically this involves such things as populating classes with needed data or making sure that databases have the correct records. We give each class in the hierarchy the opportunity to do any setup and cleanup. For setup we start at the root test class and work down to our immediate superclass. For cleanup we do this in reverse, starting at our superclass and working up to the root test class. We'll run setup and cleanup for the current test and its subtests later.

(One thing to note is that we assume the setup and cleanup will work. This test manager doesn't have the ability to handle problems in setup and cleanup, or handle exceptions raised there.)

We have a method that determines whether any setup should be done, and another method that does the setup for all the superclasses in the hierarchy. We won't show them, but there are similar methods for doing cleanup.
```kotlin
TstTestManager>>myDoSetupFor: aClass
(aClass class includesSelector: #setup)
ifTrue: [aClassupa]

TstTestManager>>myDoHierarchySetupFor: aClass
aClass testSuperclasses
reverseDo: [each | self myDoSetupFor: each]
```

A feature of our setup is that we don't want to inherit setup methods from superclasses. If we allowed inheritance, we would do the same setup more than once if a particular class in the hierarchy didn't need to do any setup. We handle this with the code:

each class includesSelector: #setup

This code checks to see if the named selector has been defined by the class. We can't use `respondsTo:` because this will also return *true* if the method is inherited from a superclass, which we specifically don't want. The cleanup methods looks very similar except that they use `cleanUp` rather than `setup`, and because cleanup should occur in the opposite order to setup, `myDoHierarchy CleanupFor: sends do: rather than reverseDo:.`

A point to note is that we define the `setup` and `cleanUp` methods on the class of the test classes side rather than the instance side. This is because we want to potentially invoke these methods for several classes in the test case hierarchy. The only way we could do this on the instance side would be to create an instance of each class in the hierarchy, then send it the message. It's a lot cleaner to put the behavior on the class side.

Here is another method for which we need to look at the code.

```kotlin
TstTestManager>>myRunTestsForClass: aClass result: aTestResult
self myDoSetupFor: aClass.
aClass individualTests
do: [each | each run: aTestResult].
aClass subclasses do:
  [each | self myRunTestsForClass: each result: aTestResult].
self myDo CleanupFor: aClass
```

When we run tests for a class, we do any set up for the test class we are running, we run any individual tests defined on the test class, we go through all our sub tests, asking them to do exactly what we are doing, then we do any clean up for the test class. So in this method, we recursively ask all our subclasses to execute this same method. This gives us a depth first recursion through the whole sub test hierarchy for this test. Well, that's it for running a hierarchy of tests. The other way to run tests is by selecting individual tests to run.

## Selected Tests

The Test Manager has a different philosophy when running individual tests. Rather than going through all the setup and cleanup of classes higher in the test hierarchy, it assumes that any setup has already been done (you can change this by clicking the Run setup/cleanup check box). However, it *does* do setup and cleanup for the current test class. It also runs the tests without a test result wrapper, which means that if an individual test fails, it will raise a Notifier window and let you start debugging. You can select multiple tests to run in the individual test window, then when you press the Run button, the `runSelected` method is executed.

```kotlin
TstTestManager>>runSelected
```
```kotlin
| selectedTests testClass testCollection |
selectedTests := self individualTestList selections.
selectedTests empty ifTrue: [^self].
testClass := self mainTest value.
testCollection:= selectedTests collect: [:each | testClass
newTest: each].
self doSetup Cleanup value ifTrue: [self myDoHierarchySetupFor:
testClass].
self myRunSelectedCases: testCollection forClass: testClass.
self doSetup Cleanup value ifTrue: [self myDoHierarchy CleanupFor:
testClass]].
```

If any individual tests have been selected, we create a collection of test objects, one for each test selected. We then run the selection in another method.

```kotlin
TstTestManager>>myRunSelectedCases: aCollection forClass: aClass
self myDoSetupFor: aClass.
aCollection do: [:each | each run].
self myDo CleanupFor: aClass
```

At this point we do setup for the class we are in, we run each test without a test result wrapper, then we do any cleanup. Because we are not using a test result, any failure will cause a Notifier window to be displayed.

## Running tests that never complete

Some tests may never complete because they are waiting for something that doesn't happen. This presents a problem in the current scheme because the rest of the tests will never run, and you will not see the test result. If you have such a situation, you can replace the `performTest` method with the following code. However, a more likely scenario is that you have only a few tests with the potential to wait forever. For example, your System Tests might have the potential to hang, but other tests will always complete. In this case, you would override `performTest` in the SystemTest class. Or you could set up a two branch hierarchy under TstTest, one branch for tests that have the potential to hang and one branch for those that don't.

```kotlin
TstTestManager>>performTest
| testProcess timeoutProcess sharedQueue exceptionOrNil |
super class showContext: thisContext.
sharedQueue := SharedQueue new.
testProcess :=
    [self errorSignal
        handle: [:ex | sharedQueue nextPut: ex]
        do:
            [self perform: selector.
             sharedQueue nextPut: nil]] fork.
timeoutProcess :=
    [(Delay forSeconds: self timeoutValue) wait.
     sharedQueue nextPut: (self errorSignal newException
      errorString: 'TIMEOUT')] fork.
exceptionOrNil := sharedQueue next.
testProcess terminate.
timeoutProcess terminate.
exceptionOrNil notNil ifTrue:
    [exceptionOrNil propagateFrom: thisContext]
```

We run the test in a forked process and create another forked process that will wait for some timeout period. Both forked processes put something on a SharedQueue when they have done their work, and the main flow
waits until it can read something from the queue. It then takes action based on what it gets off the queue. Let's
look at the details.

In *testProcess* we run the test, wrapped in an all-encompassing signal handler. If the test succeeds, we put *nil* on the shared queue. Seeing *nil* tells the main flow that the test succeeded. If the test does not succeed, an exception is raised as we saw earlier in the chapter. We trap the exception and put it on the shared queue. In *timeoutProcess* we simply wait for some timeout period then we create an exception and put it on the shared queue. Since we are using a message send to get the timeout value (you'll have to write the *timeoutValue* method and have it return a number), subclasses can override the value if they need a different timeout period.

The main flow of control waits for one of the processes to put something on the shared queue. This will either be *nil*, which means the test succeeded, or an exception, which we raise again so that the code in the *run* or *run*: method can handle it appropriately. It also terminates both forked processes since they are no longer needed (sending *terminate* to an already terminated process is benign).

We do things this way because when a process is forked it gets its own context. A signal handler in one context can't trap an exception raised in another context, so we trap the signal in the forked process, give it to the main process, and let the main process start it up again as though it came from the main process.

Loading in the tests

Besides having a mechanism for filing in all the tests or a subset of the tests, you might find it useful to have
each class responsible for filing in tests that test it. A mechanism for doing this is to have fileIn code in a class-
side method such as:

MyClass class>>fileInTests
"self fileInTests"
#( 'MyTest1.st'
'MyTest2.st'
) do: [:each | (self myTestDir construct: each) fileIn]

In this chapter we have looked at a test scheme that makes use of a test manager to run the tests. We could extend this scheme and give each class the ability to test itself using the TstClass functionality. For example, we might write a method such as the following on the class side of classes we wish to test.

MyClass class>>runTests
"self runTests"
#( MyTestOne
MyTestTwo
) do: [:ClassName | (Smalltalk at: classname) individualTests do:
[:test | test run]]

However, the technique shown still relies on there being separate classes to do the testing. An alternative
scheme would be to keep the test cases completely within the classes to be tested, but such a scheme goes
beyond the scope of this chapter.
31

Customizing your Environment

One of the things that makes Smalltalk development so much fun is that you can easily modify the development environment. If you don't like something, change it. This chapter contains examples of such changes. They are preferences of mine but not necessarily those of everyone (if they were so good, they'd be part of the standard image). To make the changes part of your standard environment, you can either save the image with your changes, or file the changes in every time you start up the image. For more information on filing in changes, see Chapter 33, Managing Source Code.

Keyboard

In VisualWorks the delete key and the backspace key work identically, both deleting the character to the left of the cursor. To change the delete key so it deletes to the right of the cursor, evaluate the following.

LookPreferences deleteForward: true.

Another change I like to make is to map ctrl-X, ctrl-C, and ctrl-V to Cut, Copy, and Paste, as is standard in
Windows applications. I also map ctrl-A to Accept. One way to remap your keyboard is to modify the class side
method initializeDispatchTable in ParagraphEditor. If you make the following changes, you
must execute ParagraphEditor initializeDispatchTable after accepting the method. This is most
easily done by selecting the text in quotes at the top of the method and executing do it. The will take effect in the
next Browser you open, so close your current Browsers and open new ones.

ParagraphEditor class>>initializeDispatchTable
...
Keyboard bindValue: #cutKey: to: Ctrlx.
Keyboard bindValue: #copyKey: to: Ctrlc.
Keyboard bindValue: #pasteKey: to: Ctrlv.
Keyboard bindValue: #acceptKey: to: Ctrla.
....

This approach is a reasonable one if everyone will be getting the same keyboard mapping. An alternative
way, which allows developers to easily customize their own keyboard maps, is to create a new class method,
`keyboard`, for `ParagraphEditor` that returns the class variable, `Keyboard`. Once you have this method, you can modify the keyboard bindings by sending `bindValue:to:` messages to the keyboard. This scheme has the advantage that programmers don't have to change the `initializeDispatchTable` method, or reinitialize it. As before, the changes will only take effect when new Browsers are opened. Here's some code showing how this approach might work.

```kts
ParagraphEditor class>>keyboard
    ^Keyboard

ParagraphEditor keyboard
    bindValue: #cutKey: to: (TextConstants at: #Ctrlx);
    bindValue: #copyKey: to: (TextConstants at: #Ctrlc);
    bindValue: #pasteKey: to: (TextConstants at: #Ctrlv);
    bindValue: #acceptKey: to: (TextConstants at: #Ctrla).
```

The wonderful thing about Smalltalk is that there are many ways to do things. If you don't want to add methods to system classes, there is yet another approach to take. We can directly get hold of the `Keyboard` class variable, then send it the relevant messages. For example,

```kts
(ParagraphEditor classPool at: #Keyboard)
    bindValue: #cutKey: to: (TextConstants at: #Ctrlx).
```

`Ctrlx`, etc., are found in the `TextConstants` pool dictionary. `ParagraphEditor` has specified `TextConstants` as a pool dictionary, but if you evaluate the above line in a workspace you have to specify where to find `Ctrlx`. At this point we are not quite done, because by default `ctrl-C` is the interrupt key, which takes precedence over Copy. We need to remap the interrupt key to something else. I choose `ctrl-Q` because it is easily remembered (`Q = quit`).

```kts
InputState interruptKeyValue: (TextConstants at: #Ctrlq).
```

If you don't like to remap `ctrl-C` but would still like these changes, and alternative technique would be to map the keys to a double key combination. For example, we might map `Cut`, `Copy`, and `Paste` to `Esc-x`, `Esc-c`, `Esc-v`. Here's an example of doing this, assuming we have a `keyboard` method.

```kts
ParagraphEditor keyboard
    bindValue: #cutKey: to: (TextConstants at: #ESC) followedBy: $x;
    bindValue: #copyKey: to: (TextConstants at: #ESC) followedBy: $c;
    bindValue: #pasteKey: to: (TextConstants at: #ESC) followedBy: $v.
```

Besides these changes, I also remap the `Replace` and `Search` keys and include several emacs key bindings such as `ctrl-D` for delete-character, `ctrl-K` for delete-to-end-of-line, and `ctrl-E` for end-of-line. The emacs key-bindings code is available from the Smalltalk Archives (see Chapter 35, Public Domain Code and Information). If you have a Sun keyboard, you can map the keys on the left by using `#L1`, `#L2`, etc., as the names. For example,

```kts
Keyboard bindValue: #copyKey: to: #L6.
Keyboard bindValue: #pasteKey: to: #L8.
Keyboard bindValue: #cutKey: to: #L10.
```
## VisualWorks 2.5 change

In VisualWorks 2.5, the TextEditorController gets its own copy of the keyboard table from ParagraphEditor, its superclass. If you make changes to ParagraphEditor's keyboard table, you will need to reinitialize TextEditorController after making the changes and before opening new windows.

```k language
TextEditorController initialize
```

## Launcher

There are several changes I like to make to the Launcher. However, rather than changing the class *VisualLauncher*, we'll create a *MyVisualLauncher* as a subclass of *VisualLauncher*. Here are some examples of what we might add to it. Because the launchers are created differently in VisualWorks 2.0 and 2.5, we'll show the differences where appropriate. (You can find the source code in the files `launch20.st` and `launch25.st`.) After making the changes, open a *MyVisualLauncher* and close the old *VisualLauncher*. Figure 31-1 shows the customized Launcher.

<figure><img src="image_55.png" /><figcaption>Figure 31-1. The customized Launcher.</figcaption></figure>

## Window label

The first thing we'll do is modify the window label so that it's obvious we're not using a standard Visual Launcher. We change the label after the window is built, but before it is displayed.

```k language
MyVisualLauncher>>postBuildWith: aBuilder
    super postBuildWith: aBuilder.
aBuilder window label: 'My VisualLauncher'
```

## Other menu

Next we add a new menu to the menu bar, the *Other* menu. This is where we will put most of our additional actions that we'd like to invoke from the Launcher. The Other menu will look like the following.

<figure><img src="image_56.png" /><figcaption>Figure 31-2. The Other menu.</figcaption></figure>
We'll add the new Other menu to the end of the menu bar, which we do by overriding the `newMenuBar` method and adding a new menu item to the end.

```k language="k language="k language="k language="k
MyVisualLauncher>>newMenuBar
| menuItem |
menuItem := MenuItem labeled: 'Other'.
menuItem submenu: self class otherMenu.
^(super newMenuBar) addItem: menuItem; yourself
```

## VisualWorks 2.0

Copy the `browseMenu` method in the class side `resources` protocol of VisualLauncher to the new `MyVisualLauncher` class. Modify the name to `otherMenu` both in the method name and in the comment. Accept the method, then highlight the text inside the comment and do it, which brings up a menu editor.

Modify the menu text and method names to look like the following then press the Build button followed by the Install button. Press OK when given the Install screen. Note that a Tab separates the menu item name from the method name. What follows are some items that I like to include in my Other menu. Obviously you can add your own favorite actions and modify or remove the ones shown here.

```
Coding Assistant otherOpenCodingAssistant
Copy Class otherCopyClass
Remove... nil
Window otherRemoveWindow
Dialogs otherRemoveDialog
Open Files... nil
Inspect otherInspectOpenFiles
Close otherCloseFile
Inspect... nil
Smalltalk otherInspectSmalltalk
Undeclared otherInspectUndeclared
Instances... nil
Inspect otherInspectInstances
Remove otherRemoveInstances
```

## VisualWorks 2.5

In VisualWorks 2.5 you can directly edit the menu bar using the menu editor, placing the *Other* menu wherever you think appropriate. However, you must first select Settings from the File menu, then choose *Use Enhanced Tools* in the UI Options tab. If you don't use the Enhanced Tools, the menu will not be correctly built and you will get an exception when you open the new Launcher.

However, we will add the Other menu to the end of the menu bar without modifying the `menuBar` method, which allows us to inherit the VisualLauncher menu bar. In the ResourceFinder, highlight `MyVisualLauncher` then select `New Menu` from the `Resources` menu. Add the items shown above then install your changes by selecting `Install` from the `Menu` menu.

## Both

Moving to the instance side of `MyVisualLauncher`, in a new `actions` protocol write the following methods. Once you've added this code, open a new Launcher by executing `MyVisualLauncher open` in a workspace, and close the old Launcher.

```k language="k language="k language="k language="k
MyVisualLauncher>>otherInspectSmalltalk
```
Smalltalk inspect

MyVisualLauncher>>otherInspectUndeclared
Undeclared inspect

MyVisualLauncher>>otherOpenCodingAssistant
CodingAssistant open

The following methods inspect and close open files. It's possible to lose a reference to a file without having closed it, especially if an exception is raised in the file reading or writing code. The garbage collector will collect your file object, but won't close the file on disk.

MyVisualLauncher>>otherInspectOpenFiles
(ExternalStream classPool at: #OpenStreams) copy inspect

MyVisualLauncher>>otherCloseFile
| path count |
count := 0.
path := Dialog request: 'Full path for file you want to close?'
initialAnswer: ''.
(ExternalStream classPool at: #OpenStreams) copy
do: [:each | each name = path
ifTrue:
    [each close.
    count := count + 1]].
Dialog warn: 'Closed ', count printString, ' files'

The next methods remove windows that are on the screen but which you can't remove the normal way. Sometimes windows won't close, and sometimes dialogs are left orphaned if the code associated with them raises an exception.

MyVisualLauncher>>otherRemoveDialog
"Close orphan dialogs"
ScheduledControllers scheduledControllers
do: [:each | (each isKindOf: ApplicationDialogController)
ifTrue: [each closeAndUnschedule]]

MyVisualLauncher>> otherRemoveWindow
| label |
label := Dialog request: 'Label for window you want to remove?'
initialAnswer: ''.
ScheduledControllers scheduledControllers
do: [:each |
(each view label = label or: [each view label = label
asSymbol])
ifTrue: [each closeAndUnschedule]]

The next methods inspect and remove instances of a class. Sometimes you will have instances that won't disappear. This indicates a problem with your application in that some object is still referencing the instance. However, you may still want to get rid of the instances. Be careful of this feature though; if you remove instances of system classes such as OrderedCollection, your system will no longer function correctly, if at all. (Also, don't plan on saving the image because there is something wrong with your application and it is not releasing objects correctly.) We use the become: message to change each instance of the class to a new instance of String. In VisualWorks, become: swaps all references to the receiver and to the argument. So, every object that referenced the instance of the specified class now references a new instance of String. Also,
every reference to this new instance of String now holds onto the instance of the specified class. Since the string
is new, there are no objects holding onto it, so your instances will now be garbage collected. (If you try and
make something become nil, you will swap the references so that every place that referred to nil will now refer to
the instance of the specified class, which will cause untold problems.)

MyVisualLauncher>>otherInspectInstances
| class classname
NESS
NESS
NESS
initialAnswer: ''.
class := Smalltalk at: classname asSymbol ifAbsent: [nil].
class notNil
    ifTrue: [class allInstances inspect]
    ifFalse: [Dialog warn: 'This class does not exist']

MyVisualLauncher>>otherRemoveInstances
| class classname count |
className := Dialog request: 'Class for which to remove
instances?' initialAnswer: ''.
class := Smalltalk at: classname asSymbol ifAbsent: [nil].
class notNil
ifTrue:
    [count := class allInstances size.
     class allInstancesDo: [:each | each become: String new].
     Dialog warn: 'Removed ', count printString, ' instances']
ifFalse: [Dialog warn: 'This class does not exist']

Sometimes you will decide that a class has too much responsibility and will split it into two classes. The
easiest way to do this is to start with two identical classes and remove the methods that are not needed. One way
to create a copy of the class is to file it out, change the class name, then file the original class back in (in Envy,
you can't rename classes so you'll have to change the name in the disk file). Another approach is to add a menu
item to the Launcher.

MyVisualLauncher>>otherCopyClass
| sourceName sourceClass destinationName writeStream newSourceCode
| 
sourceName := Dialog request: 'Class to Copy?'.
sourceClass := Smalltalk at: sourceName asSymbol ifAbsent:
    [^Dialog warn: 'This class does not exist'].
destinationName := Dialog request: 'New Class?' initialAnswer: ''.
destinationName = '' ifTrue: [^self].
(Smalltalk at: destinationName asSymbol ifAbsent: [nil]) notNil
    ifTrue: [^Dialog warn: 'This class already exists'].
writeStream := (String new: 1000) writeStream.
sourceClass fileOutSourceOn: (SourceCodeStream on: writeStream).
newSourceCode := writeStream contents
copyReplaceAll: sourceName
    with: destinationName.
newSourceCode readStream fileIn

Changes

Let's make a couple of changes to the Changes menu. I like to have *Inspect Change Set* at the top, and I like
to add a *Condense Changes* option. All the code that you write is compiled into byte-codes and these byte-codes
stay in the image when you save it. However, the source code goes into the change file, which records all the
modifications to classes and methods. Because the change file grows as you make changes to your application,
it's a good idea to periodically condense it, removing all but the most recent version of your code. (Alternatively, you could periodically start with a fresh image and save it under your name.) Here's what the new Changes menu will look like.

<figure><img src="image_57.png" /><figcaption>**Figure 31-3.**
The Change Menu.</figcaption></figure>

## VisualWorks 2.0

For VisualWorks 2.0, go to the `resources` protocol on the class side and copy `changesMenu` from `VisualLauncher` to `MyVisualLauncher`. In the `changesMenu` method, highlight the text inside the command, and *do it*. Change the order of the menu items to put `Inspect Change Set` at the top, then add the entry shown below.

## VisualWorks 2.5

For VisualWorks 2.5, you'll need to make sure that you have selected Enhanced Tools in the Settings. Copy over the `menuBar` method from the `VisualLauncher` class side `resources` protocol to `MyVisualLauncher`. Change the order of the menu items to put `Inspect Change Set` at the top of the `Change` menu, then add the entry shown below.

## Both

For both VisualWorks 2.0 and 2.5, add the following to the `Changes` menu.

```
Condense Changes changesCondenseChanges
```

Now we need to write the `changesCondenseChanges` method in the instance side `actions` protocol and open a new `Launcher`.

```
MyVisualLauncher>>changesCondenseChanges
SourceFileManager default condenseChanges
```

The `condenseChanges` message removes all but the most recent versions of the methods and classes in the `changes` file. A similar message, `condenseChangesOntoSources`, adds the most recent changes to the `sources` file (visual.sou), removing all changes from the `changes` file. This latter message is useful after you get a new release of the software and you want to add code that will be part of the base image, such as the Advanced Tools. If you add the new code then do `SourceFileManager default condenseChangesOntoSources`, the changes will be added to the source file and will be available to everyone. You could certainly leave the changes in the `change` file, but then everyone would get a larger change
file than necessary. In regular use you definitely do *not* want developers to condense their changes onto the source file. General usage should be to condense changes within the changes file.

If we simply wanted to add a group of menu items to the end of the menu, we wouldn't need to override the `changesMenu` method. Instead we could add items to the end of the menu by adding more code to the `newMenuBar` method.

```kotlin
MyVisualLauncher>>newMenuBar
    | menuItem menuLabels menu Selectors changesMenu newMenuBar |
    | newMenuBar := super newMenuBar.
    | menuItem := MenuItem labeled: 'Other'.
    | menuItem submenu: self class otherMenu.
    | newMenuBar addItem: menuItem.
    | menuLabels := #('Condense changes').
    | menu Selectors := #(#changesCondenseChanges).
    | changesMenu := newMenuBar menuItemLabeled: 'Changes'.
    | changesMenu submenu addItemGroupLabels: menuLabels values:
    | menu Selectors.
    | ^newMenuBar
```

## Default browser

I prefer to use the System Full Browser rather than the System Browser, so I'd rather have the Browser button bring up a Full Browser. To do this, we simply override `browseAllClasses` as follows.

```kotlin
MyVisualLauncher>>browseAllClasses
    self openApplicationForClassNamed: #FullBrowser
```

## Adding VisualLauncher menus to a mouse button

If you use a virtual desktop such as mvwm or HP Dashboard®, you may find yourself moving Browsers and other windows onto other virtual screens. Then you may find yourself either moving between desktops whenever you want to use the Launcher, or creating additional Launchers for your other desktops. Below is some code that will add the Launcher menus to the mouse window menu. This is the right hand mouse button on a three-button mouse (eg, for Unix workstations), or Ctrl-Righthand mouse button on a two-button mouse (eg, for PCs). We use the window menu rather than the operate menu because the window menu is defined only in one place, whereas the operate menu is context sensitive and is defined in many places.

```kotlin
windowMenu := StandardSystemController classPool at:
    #ScheduledBlueButtonMenu.
    launcherItem := windowMenu menuItemLabeled: 'Launcher' ifNone:
        [nil].
    launcherItem notNil ifTrue: [windowMenu removeItem: launcherItem].
    menuItems := MyVisualLauncher new newMenuBar menuItems.
    submenu := Menu new addItemGroup: menuItems.
    windowMenu addItem:
        ((MenuItem labeled: 'Launcher') submenu: submenu)
```

You will also need to make a change to `StandardSystemController`, to redirect execution from the controller to a `MyVisualLauncher`. It's definitely a hack, but it works quite nicely. In `StandardSystemController>>blueButtonActivity`, find the code at the bottom that says `self perform:choice`. Modify this to be the following:
(self correspondsTo: choice)
    ifTrue: [self perform: choice]
    ifFalse: [MyVisualLauncher new perform: choice]

If you are using ENVY, you could extend the window menu by executing:

windowMenu := StandardSystemController classPool at:
#ScheduledBlueButtonMenu.
windowMenu menuItemLabeled: 'ENVY'
    ifNone:
        [windowMenu addItem:
            ((MenuItem labeled: 'ENVY') submenu: VisualLauncher
             browseMenu)].

You would then modify `blueButtonActivity` to read as follows. This works because the ENVY menu returns a block rather than a method to perform.

(choice isSymbol)
    ifTrue: [self perform: choice]
    ifFalse: [choice value].

## Templates

To change the method template (the thing you see if you have a protocol selected but no method selected), modify `sourceCodeTemplate` for class `Behavior`. To put in a date and copyright, do something like the following. If you want anything more sophisticated, it might be clearer to use a `Stream` to build up the string.

Behavior>>sourceCodeTemplate
    ^' methodName
    "Copyright My Company: ', Date today printString, ' ', Time now
    printString, '"

Another change that you might want to make for methods is to record each modification to a method. The starting point for this is `TextController>>doAccept`, but the modifications are non-trivial.

If you want to change the class comment template so that it gives a specific layout for the comments you want developers to write, you can modify `ClassDescription>>commentTemplateString`. Take a look at the comments for a few of the system classes (such as `Date` and `KeyedCollection`) and use them as a guideline for building your own template.

## Screen Color

If you want to change the colors of the development environment, the easiest way to do so is to go to the appropriate `WidgetPolicy` class. If you are using Motif widgets on a Unix workstation, you can modify the class side method `initializeDefaultGenericColors` to specify the colors you want, such as shown below, then execute `MotifWidgetPolicy initializeDefaultGenericColors`.

MotifWidgetPolicy class>>initializeDefaultGenericColors
    ...
    matchAt: SymbolicPaint background put: (background := ColorValue
    lightCyan);
    matchAt: SymbolicPaint selectionBackground put: ColorValue pink;
```kscript
matchAt: SymbolicPaint selectionForeground put: ColorValue black.
...
```

Alternatively, you can change the colors by sending messages rather than modifying a system method, which is more appropriate if you want to change the colors using a fileIn. To do this, send `matchAt:put:` messages to the appropriate object. Again, if it is a Motif widget, you would do the following:

```kscript
MotifWidgetPolicy defaultColorWidgetColors
matchAt: SymbolicPaint background put: ColorValue lightCyan;
matchAt: SymbolicPaint selectionBackground put: ColorValue pink.
```

Once you've done this, you need to update the default screen and refresh the display. You can execute the following lines to accomplish this.

```kscript
Screen default updatePaintPreferences.
ScheduledControllers restore.
```

If you are not on a platform that runs X, VisualWorks pays attention to the color scheme you chose for the platform (on Windows, these are the colors specified in the Control Panel). To disable this and make VisualWorks pay attention to the colors you specify using the mechanism above, comment out the line that says `self installPlatformPreferencesFrom: aGraphicsDevice on: colors` in the method `WidgetPolicy class>>defaultWidgetColorsOn:`.

## Speed up startup

On a Unix system, VisualWorks takes a long time to come up. One of the reasons is that during startup, VisualWorks looks at every font on the system. When we modified this code to only look at the fonts that are necessary, we found that the startup time went from about thirty seconds down to seven seconds. To do this change, modify the `FontPolicy>>initializeFor:` method. In it, change the following line to the three lines below.

```kscript
availableFontS := aDevice listFontNames collect: [:name | fontClass parse: name].

availableFontS := false
    ifTrue: [aDevice listFontNames collect: [:name | fontClass parse: name]]
    ifFalse: [self necessaryFontS collect: [:name | fontClass parse: name]]
```

To get the list of fonts that should be returned in the `necessaryFontS` method, inspect `Screen default`. From the inspector, inspect `openFontS`. Highlight the array of Associations and move it into the `necessaryFontS` method. You'll need to remove the value part of each association and make the strings into a literal array. You should end up with something like the method shown here.

```kscript
necessaryFontS
    ^#('adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1'
        ...
        '-adobe-helvetica-medium-r-normal--14-140-75-75-p-77-iso8859-1')
```
These changes will take effect the next time you load the image so save the image, exit, and restart
VisualWorks. If you want to revert back to reading all the fonts (perhaps you are going to run the image on
another type of computer), simply change the *false* to *true* in `FontPolicy>>initializeFor:`.
32

Changes to System Classes

Sometimes it is useful to modify system classes. To be able to add a method to Object that everyone can
inherit can make life much easier. In fact, in several chapters in this book we've seen new methods added to
system classes. There are several kinds of change you can make and we'll look at them in this chapter.

Some people feel it is inappropriate to modify system classes for various reasons. The arguments listed below
are all valid arguments, and after reading this chapter you will have to decide where your own beliefs lie.

* If you change a system class then get a new release of the system software, your change will not be there. It may be difficult to put back in because of possible restructuring of system classes. You may simply forget to reimplement the change and this may not be discovered until a customer uses the software.

* The system classes are highly reliable. Any change you make could detract from that reliability.

* Programmers won't know that certain behaviors were added and will expect to find the changes in other projects they work on.

* Programmers may expect a method to behave a particular way, then discover too late that the method was modified to behave a different way.

Subclass where possible

It's better to subclass off a system class than to add a method or modify a method. It's not always possible to subclass, as we'll see, but the failure to subclass is often a result of not attempting to subclass. For example, when I originally extended the VisualLauncher with a few changes, I simply added new methods. Only later did it dawn on me to subclass from VisualLauncher. Besides the virtues of not modifying system classes, subclassing has the additional virtue that it is obvious when programmers are using a non-standard class.

If you want to add behavior to Object that you want inherited by all your application objects, consider
creating a new class, *MyApplicationObject*, that is subclassed off Object. If you subclass all your application
objects from MyApplicationObject, you can now add application specific behavior that all your objects will
inherit, without having to modify Object in any way. We saw an example of this in Chapter 5, Instance Creation.
## Types of changes to system classes

There are two facets to consider when talking about changing system classes. First is that some changes will be to classes used in the development environment, while others will be to more fundamental classes that are used in your deployed application. The other facet is that there is a difference between adding methods to system classes and modifying existing methods.

## Development environment vs. deployed classes

There are changes that you can make to your development environment that will never be executed in a deployed application. More importantly, there are changes that you can make to your development environment that don't have to be incorporated into the production application. For example, you might make changes to remap your keyboard for development, to allow resizing of Browser panes, or to add more sophisticated breakpoints. None of these changes have to be included when building the application for testing and deployment.

## Added vs Modified methods

Adding methods to system classes is a lot less risky than modifying existing methods. When you modify a method, you have to be very careful that your change will not cause harm to any of the senders of the message. Sometimes this is easy to determine, sometimes difficult. Avoid modifying a method in a way that will confuse programmers who expect certain results from message sends. To use an extreme example, if someone modified `add:` to return `self` rather than the object added, the result is likely to be confusion and code that no longer works.

Adding functionality by subclassing is the right thing to do when possible, but it's not always possible or easy. Suppose we want to add `trimWhiteSpace` to remove leading and trailing white space from a string. It's not easy to add a subclass of `String` because `String` new actually returns a subclass of `String`, and creating a literal string, such as `'hi there'`, will not create an instance of our new subclass. So, it's much easier to add `trimWhiteSpace` to `String`.

In fact, I'm all in favor of adding methods as long as they are well thought through and well tested. I'm also okay with modifying methods to extend functionality as long as the old expected behavior is preserved. For example, in Chapter 16, Processes, we looked at the idea of subclassing off Process. Unfortunately, the method `Process>>anyProcessesAbove:` assumes that there are no subclasses of Process, so in order to subclass off Process we had to modify this method to operate on instances of Process and its subclasses.

If you do have to modify a system method, try to put the smallest possible change in the modified method, and most of the processing in another method (on one of your objects if possible). You might end up with something like the following.

```
SystemClass>>someModifiedMethod
...
self doNewThing.
anInstanceOfMyClass doAnotherNewThing.
...
SystemClass>>doNewThing
"Here's where most of the new code might be"
```
MyClass>>doAnotherNewThing
"Here's another place where most of the new code might be"

## Summary

* Subclass where possible.

* Be comfortable adding well-tested methods to system classes.

* Don't worry too much about modifications to system classes for development environment changes if you don't need those changes in the deployed image.

* Selectively modify fundamental system classes as long as you are extending functionality rather than modifying functionality.

## Distinguishing your additions and modifications

For two reasons, it's important to be able to distinguish system methods you've added and modified from base system methods. First, it's only fair to give programmers information that they are using non-standard methods. Second, when you get a new release, you need to be able to identify the changes you've made so that you can add them to the new image.

There are two mechanisms I use. The first is to group all added methods into protocols called (`additions`) and to move all modified methods to protocols called (`modifications`). Yes, the parentheses are part of the name — it makes the name stand out. Chapter 29, Meta-Programming, tells you how to find all classes with protocols named (`additions`) or (`modifications`).

However, I don't do this for development environment changes that I get from the Smalltalk archives or similar places. Some of these fileIns make such extensive changes to system classes that it's more important to make sure they are only in development environments and not in production applications.

The second mechanism I use to distinguish my changes from the standard classes is to place one of the following statements as the first executable line in the methods (the method definitions are shown later in the chapter). By noting new methods and changed methods in this way, it's easy to find all the new or changed methods by browsing references to either `newMethod:` or `changedMethod:`.

`self newMethod: 'Date. Author. Why'.`

`self changedMethod: 'When. Who. Why'.`

Why use both the message sends and the protocol name? In part, to increase my chances of tracking all the changes that I have to carry forward to new releases. However, the two mechanisms do serve different purposes. When I want to find a method I wrote but can't remember the details of, looking for message references will get me there quickly. If I'm browsing a class, the special protocol names tell me immediately that there are extensions or modifications to the class. By grouping added and modified methods, I can easily file out all the changes to system classes by choosing the *file out* menu option from the protocol window.
## Some useful additions

This next section shows a few minor additions to *Object* that I've found useful. We've seen additions and changes to system classes in other chapters, but we are not repeating them here.

The following methods make it much easier to print information to the Transcript. Some people find it easier conceptually to use the `echoYourself` methods, but once you get used to the idea of objects printing themselves to the Transcript, it's less typing to use the `echo` methods. The code is based on Ernest Micklei's `echo.st` contribution to the Smalltalk archives.

```
Object>>echo
Transcript cr; nextPutAll: self displayString; flush
```

```
Object>>echo: anObject
Transcript
cr; nextPutAll: self displayString;
space; nextPutAll: anObject displayString;
flush
```

```
Object>>echoYourself
self echo
```

```
Object echoYourselfAnd: anObject
self echo: anObject
```

The next few methods don't do anything. They exist simply so that you can find all references to them.

```
Object>>newMethod: aString
"Does nothing. Used to find methods added to system classes"
```

```
Object>>changedMethod: aString
"Does nothing. Used to find system class methods that have been
changed"
```

```
Object>>obsoleteMethod: aString
"Does nothing. Used to find obsolete methods"
```

```
Object>>optimizePoint: aString
"Does nothing. Used to find methods that need additional work"
```
33

Managing Source Code

In the description that follows, I am assuming that you are not using a product such as ENVY to manage your
source code and configurations. Instead, you are using some combination of filing out your changes, saving your
image, and filing in your changes. We'll talk more about ENVY in Chapter 34, ENVY.

As you work, you are probably saving your changes in some way, whether it's by filing out categories, classes, or methods, or by periodically saving your image. Certainly you'll need to file out your changes if other developers are to incorporate them. Whatever technique you use to protect your work from crashes and to distribute your changes to others, it's important to be able to rebuild your image with all the correct code.

The technique that I've usually used is to rely on developers filing out changes, usually at the class category level, then every day starting up a clean image — one containing no source code — and filing in all the latest code. If you choose to save your image periodically instead of filing out your changes, then I recommend that you also have available a clean image you can start from, again filing in the latest code. In what follows, we'll look closely at some of the aspects of filing out code and filing in code.

What we describe is certainly not the only way to manage your source code and may not even the best way.
If you have a very large application, it may take too long to do what is shown here more than perhaps once a
week. It may be a better option to maintain an *application base image* that contains all the needed system class
additions and modifications, using a fileIn such as shown below to build the application base. Derived from the
application base might be a *developer base image* that also contains development environment changes that are
expected to be in the images of all developers. Again, this could be maintained using some of the code shown
below. Derived from the developer base might be *individual base images* that contain the preferences of
individual developers. Again, the code below can help track those changes. Periodically the developers would
file in all the latest application code, then would save their new *working image*. Also periodically, the latest
application code would be filed into the application base image and saved as a *testing image*.

Treat the code shown as possibility code. Take what you like, discard what you don't like, and above all, use
it to generate ideas that work for your development environment.
```
 sourceDir := 'c:\alec\st\source' asFilename.
sysAddDir := 'c:\alec\st\sysadds' asFilename.
sysModDir := 'c:\alec\st\sysmods' asFilename.
localFile := 'c:\visual\local\local.st' asFilename].
```

If the directories are subdirectories of a base directory, we could write code without hard-coding the base directory. In the example that follows, we assume that `install.st` is being filed in from the base directory. The idea is that we trace the context back until we find a stream, which we assume is the stream filing in this file. Once we have the base directory, we can build up the subdirectories. An example of this code can be found in the `manage` directory in the file `install2.st`.

```kotlin
context := thisContext.
[context receiver isKindOf: Stream]
whileFalse:
    [context := context sender].
baseDir := context receiver name asFilename head asFilename.
sourceDir := baseDir construct: 'source'.
```

The next section files in any system additions and system modifications that are required for the application. It makes the assumption that it should file in all the `.st` files in these directories. In other words, if you don't want something filed in, don't put it in one of these directories.

```kotlin
"File in any required system additions and modifications that we
find"
(sysAddDir filesMatching: '*.st') do: [ :each | each asFilename
fileIn].
(sysModDir filesMatching: '*.st') do: [ :each | each asFilename
fileIn].
```

We now file in any development environment changes that are specific to the programmer. If there is a named file and the file is readable we go ahead and read it. The intention is that each developer will have a file with a known name in a known, but unique to them, directory, and that if this file exists, it will be filed in. The names of the directory and file will depend on what type of platform you are working on and how your computers are networked. This scheme will work also for building the deployed application image because you don't need to set up a local file for the user that creates the application image.

```kotlin
"File in any programmer-specific changes that we find"
(localFile notNil and: [localFile isReadable])
ifTrue: [localFile fileIn]
ifFalse: [Transcript cr; show: 'No local file'].
```

Before we file in the application code we want to count the number of classes and methods in the image. We'll do the same after filing in the code, then we'll be able to report how many classes and methods our application contains.

```kotlin
"Count the number of classes and methods in the image before filing
in the application code"
beforeClassCount := Smalltalk classesNames size.
beforeMethodCount := Smalltalk classesNames
inject: 0
into:     [:subtotal :each | | class|
           class := Smalltalk at: each.
```
subtotal + class selectors size + class class selectors
size].

Now we create any necessary pool dictionaries and add all the pool dictionary variables. We need to do this in a fileIn otherwise there will be problems: if the pool dictionary doesn't exist, the fileIn will raise an exception; if the pool dictionary variables don't exist, then references to them will fail when you try to accept a method or run the code.

```groovy
"Create any necessary pool dictionaries and add all the pool
dictionary variables"
Smalltalk at: #MyPoolDictionary put: Dictionary new.
MyPoolDictionary at: #PoolVariableOne put: nil.
MyPoolDictionary at: #PoolVariableTwo put: nil.
```

The next section files in all the application code. In this example, we specify exactly what application code we want in the image, unlike the system additions where we took all the files in the directory. We also assume that you filed out by class category. If you file out by class or by method, it would probably be too painful to specify all the files, and would be easier to file in every file in the directory.

```groovy
"File in all the named categories"
#( 'CatOne.st'
'CatTwo.st'
'CatThree.st'
) do: [ :each | (sourceDir construct: each) fileIn ].
```

Now we count the number of classes and methods in the image after filing in the application code, and report on the counts.

```groovy
"Count the number of classes and methods in the image after filing in
the application code,
then report on the counts."
afterClassCount := Smalltalk classesNames size.
afterMethodCount := Smalltalk classesNames
inject: 0
into: [:subtotal :each | | class|
      class := Smalltalk at: each.
      subtotal + class selectors size + class class selectors
size].
```

```groovy
Transcript
cr; nextPutAll: 'Before loading in:';
crtab; nextPutAll: 'Class count = '; print: beforeClassCount;
crtab; nextPutAll: 'Method count = '; print: beforeMethodCount;
cr; nextPutAll: 'After loading in:';
crtab; nextPutAll: 'Class count = '; print: afterClassCount;
crtab; nextPutAll: 'Method count = '; print: afterMethodCount;
cr; nextPutAll: 'New:';
crtab; nextPutAll: 'Classes = '; print: (afterClassCount -
beforeClassCount);
crtab; nextPutAll: 'Methods = '; print: (afterMethodCount -
beforeMethodCount);
endEntry.
```

The last section does any final system changes that need to be done. In particular, we empty the change set so that the Change Set just reflects changes we make after filing in our application code, and make sure that the delete key deletes in a forward direction.
```
"Do any final system changes"
LookPreferences deleteForward: true "Make the delete key delete forwards"
ChangeSet noChanges. "Empty the change set"
```

## Filing in development environment changes

Let's now look at an example of a local file that files in development environment changes. Again, explanatory text will be interspersed with the code. The code can be found in the `manage` directory in the file `local.st`.

```
"local.st - Dave's specific environment changes
When. Who.      Why.
"

| genericDir localDir |

Window platformName = 'X11'
    ifTrue:
        [genericDir := '/visual/generic'.
         localDir := '/home/alec/st/fileIns']
    ifFalse:
        [genericDir := 'c:\visual\generic'.
         localDir := 'c:\alec\st\fileIns'].
```

In this section we file in everything we find in two directories. The first one is our own personal `fileIn` directory. This allows us to include any other enhancements we need. After we've done our personal changes to the image, we then `fileIn` everything in the generic directory. These are changes that everyone should be picking up. The reason for having this is that there may be modifications to the development environment that are standard across the organization and which a programmer can expect to see in another programmer's environment.

```
"Do any personal and generic development environment fileIns"
(localDir asFilename filesMatching: '*.st') do: [ :each | each
asFilename fileIn].
(genericDir asFilename filesMatching: '*.st') do: [ :each | each
asFilename fileIn].
```

The code that follows could easily be in one of our personal `fileIns`, but instead, we'll show it here. The code shown is described in detail in Chapter 31, Customizing your Environment, so we won't explain it in depth. The next section remaps the keyboard, assuming that you have defined a `keyboard` method on `ParagraphEditor`, remaps the interrupt key, then changes the window colors.

```
"Remap the keyboard"
ParagraphEditor keyboard
    bindValue: #cutKey: to: (TextConstants at: #Ctrlx);
    bindValue: #copyKey: to: (TextConstants at: #Ctrlc);
    bindValue: #pasteKey: to: (TextConstants at: #Ctrlv);
    bindValue: #acceptKey: to: (TextConstants at: #Ctrla).
```

```
"If this is not VW2.0, initialize the TextEditorController so it gets
the new keyboard mappings"
(Smalltalk version findString: '2.0' startingAt: 1) == 0
ifTrue: [TextEditorController initialize].
```
"Change the Interrupt key from Ctrl-C to Ctrl-Q"
InputState interruptKeyValue: (TextConstants at: #Ctrlq).

"Change my window colors"
Win3WidgetPolicy defaultColorWidgetColors
matchAt: SymbolicPaint background put: ColorValue lightCyan;
matchAt: SymbolicPaint selectionBackground put: ColorValue pink;
matchAt: SymbolicPaint selectionForeground put: ColorValue black.
Screen default updatePaintPreferences.
ScheduledControllers restore.

Windows created before we remapped the keyboard still use the old keyboard bindings so we create some new windows that use the new key bindings. We want the windows to be created automatically rather than waiting for us to position them, so we tell the ScheduledWindow class not to prompt us when opening the window. We also create a SystemWorkspace-like window which contains useful statements that can be highlighted and executed.

"Create some new windows with my new key bindings"
prompt := ScheduledWindow promptForOpen.
ScheduledWindow promptForOpen: false.
FullBrowser open.
ComposedTextView
    open: (ValueHolder with: ('c:\alec\st\useful' asFilename
                                contentsOfEntireFile))
    label: 'Useful Things'
    icon: nil
    extent: 500@200.
ComposedTextView open.
ScheduledWindow promptForOpen: prompt.

## Generic Development Environment changes

In the directory containing changes to the generic development environment, we have at least one file. This file tells the Browser that when developers file out code, the changes should be removed from the Change Set.

"general.st - General Development Environment changes
Created: When. Who. Why
"

"Remove changes from the change set after doing a file out"
Browser removeChangesOnFileOut: true.

## Using a class to file in the code

Besides filing in from a text file, we could use a class to control what gets filed in. For my personal customization I use a class rather than a file because I find it easier to make changes to a class. Here's an example of the main flow of my *Customizer* class. The code for this class can be found in the file *custom.st*.

Customizer>>customize
"self new customize"
self myFileInSystemAdditions.
self myFileInSystemModifications.
self myFileInNewClasses.
self myKeyboardChanges.
self myLauncherMenu.