# 26. The Model-View-Controller Architecture

## 26.1 Introduction

The Model-View-Controller architecture (more commonly known as the MVC) is an oft misunderstood part of Smalltalk. It is the basis upon which the user interface to a system is constructed. Its influence has been so great that numerous other system builders have based their user interface facilities upon it. Indeed so all pervading has the MVC been that at a recent conference an American computer science professor queried whether VisualWorks and Smalltalk was only a user interface development environment!

One of the causes of the confusion surrounding the MVC is that conceptually it is a simple architecture, but in practice it is rather more complicated. Indeed the construction of a good graphic interface, using the MVC, is rather more of an art than a science. There are very many classes involved, which must work together in specific ways. This chapter therefore provides a basic introduction to the MVC. For a detailed understanding of the classes available and how they should be used, the reader is directed to their system manuals and the books listed at the end of this chapter.

The situation is not as bad as it seems however, as many developers will never need to use the MVC. This is because of the user interface building facilities provided by tools such as VisualWorks and Window Builder (for Smalltalk/V). These tools provide interactive drawing tools which allow the user to construct certain types of graphical interface without the need for complex programming. However, these tools build on the basic MVC architecture therefore it is useful to understand at least the basic theory. In addition, in some circumstances, it is necessary to fall back on more basic techniques (especially for highly graphic displays).

## 26.2 The MVC architecture principles

The Model-View-Controller architecture, often known just by the letters MVC, has been a feature of Smalltalk since Smalltalk -80. It is based on the concept of separating out an application from its user interface. This means that different interfaces can be used with the same application, without the application knowing about it (see Figure 26.1). The intention is that any part of the system can be changed without affecting the operation of the other. For example, in the figure, the way that the graphical interface displays the information could be changed without modifying the actual application or the textual interface. Indeed the application need not know what type of interface is currently connected to it at all.

<figure><img src="image_105.png" /><figcaption>Figure 26.1: Splitting the interface</figcaption></figure>

The intention of the MVC architecture is to separate the user interface from the underlying information model. There are a number of reasons why this is useful:
* reusability of application and / or user interface components,

* ability to develop the application and user interface separately,

* ability to inherit from different parts of the class hierarchy.

In fact, in the MVC, the user interface is further subdivided into the output (to the screen) part and the input (from the user) part. This enables different output elements (look) to be connected with different input elements (feel). Each part of the MVC therefore attempts to provide the functionality required by one of these three areas.

## 26.2.1 The structure of the MVC

The MVC is actually made up of three cooperating components. These three components are known as the Model, the View and the Controller. These three components are illustrated in Figure 26.2 and are collectively known as the MVC triad.

<figure><img src="image_106.png" /><figcaption>Figure 26.2: The use of the MVC</figcaption></figure>

This division of responsibility in the MVC is broken down in the following way:

* **Model** - The information model which handles data storage and information processing. That is, it manages the behaviour of the data in the application domain.

* **View** - Which handles the visual display (the output part). That is, it handles how the information about the application is displayed on the screen.

* **Controller** - This provides the user interaction to, or control of, the information models processing (the input part). That is, it handles the mouse and keyboard inputs.

The diagram in Figure 26.2 illustrates the idea behind each aspect of the MVC. To use the MVC architecture you must understand the division of labor within the MVC triad. However, you should be aware that in real applications, this division of labor is not always as clean as it should be. For example, controller like behaviour can leak into the view object, while view like behaviour can leak into the controller object!

In addition, you must also understand how the three elements communicate (even if you are using one of the window building tools). Of course in any application there are many objects which aren't models (or which are contained within the *model* but don't realize that they are part of a model or a graphical system). However, they invariably work with the *model* to provide the overall application.

## 26.2.2 The elements in the MVC triad

### 26.2.2.1 Models

As has already been stated a model handles data storage and information processing. That is, it handles how the application data is processed (i.e. the functionality of the system). That means that models are responsible for holding data, operating on that data and responding to requests for information. Essentially, they are exactly what you have already been looking at throughout this book: "they are one or more objects which provide some set of operations". For example, the `Statement` class in the financial manager application, which you have encountered a number of times in this book, could be considered to be a model. It held information on deposits and withdrawals. It responded to new deposits
and withdrawals and requests for the current balance. It could therefore be used with a view and a controller as part of a graphic application.

In some versions of Smalltalk (for example VisualWorks) there is an explicit class Model from which models can inherit model like behaviour. Figure 26.3 illustrates part of the Model class hierarchy. It illustrates that classes such as *Browser* and *Inspector* are actually models, which hold some data. However, there is no reason why an object which will be used as part of the MVC triad must be a subclass of *Model*.

The important point to note about an object, which will be used as a model within the MVC, is that it must provide the application functionality independent of the type of user interface being used (ignore the issue of printing the statement in the financial manager example here). In earlier chapters, we explicitly sent messages to the financial manager application via the Workspace. However, these messages could have been sent by another object, such as a banking system object, or by a controller or view object.

<figure><img src="image_107.png" /><figcaption>Figure 26.3: Part of the Model class hierarchy</figcaption></figure>

### 26.2.2.2 Views

The information held by the model is presented to a user via a view. That is, a view obtains information from the model and decides how to present that information to the user. This can be in the form of text, graphics, widgets, or combinations of these etc. However, an important point to note is that at the view should not possess any knowledge of what the data means, neither should it change it, initiate some application process because of it, or process it (other than what is necessary for the user interface). Notice that it is the view that decides how the data should be displayed independently of the model.

The result of this is that we could have one view which displays the balance after each transaction as a table, and another as a graph. Depending on which view we connect to the model, we will get a different user interface. However, we will not have had to change the model at all.

Figure 26.4 illustrates part of the *View* class hierarchy. This hierarchy illustrates how the various elements typically found in a graphical interface are different types of view. For example, a * radi Recommendation is a subclass of * LabelledButtonView, which in turn is a subclass of * BasicButtonView, which is a subclass of * SimpleView, which is a direct subclass of * View. Similarly * ScrollBar, * MenuItemView and * LauncherView are all direct subclasses of * View. This figure also illustrates one of the interesting facilities in VisualWorks. Consider the
CheckButtonView class and its subclasses. This class has five subclasses including MacCheckButtonView, Win3CheckButtonView and MotifCheckButtonView. In this case when a user requests that a CheckButtonView is created, one of its subclasses will be used depending on the user interface look requested by the user. For example, either an Apple Macintosh, Windows 3 or X/Motif style button will be displayed. Here different views can be used, without any modification of the model or the associated controller.

<figure><img src="image_108.png" /><figcaption>Figure 26.4: Part of the View class hierarchy</figcaption></figure>

### 26.2.2.3 Controllers

Controllers handle the user interaction with the application. They work in tandem with the view so that when a user clicks on a button (displayed by a view) the controller can decide what to do. For example, the controller can ask the view to confirm that the cursor was within the active area of the button and then call the method associated with that button. That is, when the button is “pressed”, the controller will ensure that the appropriate method is evaluated.

As was said earlier, all views have an associated controller (even if it is an instance of the NoController class). Therefore, in many situations there are controller classes available which mirror the view classes. For example, there is a MenuButtonController (to go with the MenuButtonView), there is a ScrollBarController (to go with the ScrollBar view) and there are various ButtonControllers. The StandardSystemController and the ApplicationStandardSystemController are used with the top most application view while many of the other controllers are used to handle input and output for small subviews (such as buttons).
<figure><img src="image_109.png" /><figcaption>Figure 26.5: Part of the Controller class hierarchy</figcaption></figure>

It might seem understandable that the model should be separated out from the user interface, but why is the input separated from the output? This is for two reasons:

* Firstly, it allows the controllers and the views to inherit from different class hierarchies. This allows the developer to overcome the limitation of single inheritance enforced by Smalltalk (but not all object oriented languages).

* Secondly, it allows different combinations of views and controllers. This may give different looks (views) or feels (controllers).

### 26.2.3 How the MVC works

You may notice that in Figure 26.6 the arrows only point from the view and controller to the model. There are no arrows from the model back to the view or controller. This is because the model does not directly know anything about its view or controller. This is partly because it does not need to know anything about them and also because it enforces this separation. A common mistake for those new to the MVC is to find that they have created instance variables in their model object which allow them to link the model directly to the view and/or controller. This is extremely poor Smalltalk style!

So how do the view and the controller find out about changes in the model. Remember, the view bases what it displays on the data held within the information model. In terms of Smalltalk relationships this means that the view is a *dependent* of the model (see last chapter). The view, must therefore, record itself as a dependent of the model (Figure 26.6 illustrates how interaction occurs between the model, view and controller). This means that it is the responsibility of the model to inform its dependents of any changes to its contents (i.e. its view). This is done by the model sending a message to itself stating that its contents has changed in some way. The *changed* method is actually defined in class *Object* and is thus inherited by all classes in the system. This means that any object in the system can act as the model in an MVC triad<fnref n="11" />. This method causes an *update* message to be sent to each of the views referenced in the dependents collection.

<footnote n="11">¹¹ This actually means that any object, irrespective of whether it is used in the MVC, can have dependents, and that those dependents can be informed of changes to the object in the same way that views are informed of changes in their associated information model.</footnote>
How the update message is handled is the responsibility of the receiver (in this case the view). For example, in order to find out what change has occurred, the view will need to request some information maintained within the model. Thus the information model only needs to send the `change` method to itself at the appropriate times, the views must then handle the `update:` message independent of the model.

<figure><img src="image_110.png" /><figcaption>Figure 26.6: The dependency relationship within the MVC</figcaption></figure>

In Figure 26.6 notice that the view and the controller both have direct links to the model and to each other. This means that the controller can send requests for services directly to the model while the view can request state information directly from the model. Also note that the controller and view both possess explicit links to each other which allows them to communicate directly. However, although the model must know that something *may* be interested in it (i.e. it must send itself one of the changed messages), it does not know what that thing is - it could be any type of object including a view. Also remember that it is the view that would have had to make itself a dependent of the model and thus the model developer need *never* know how the model would be used.

This arrangement means that:

* Views and controllers tend to be tightly coupled.

* Views and controllers come in pairs. To support this most views in VisualWorks know what controller they should have and can instantiate it for you.

* More than one view can be associated with a single model.

This last situation is known as having multiple views and is illustrated in Figure 26.7. Thus the same information can be displayed simultaneously by different views. All of which are updated as appropriate, if and when required.

<figure><img src="image_111.png" /><figcaption>Figure 26.7: Multiple views</figcaption></figure>

## 26.3 The MVC with the statement model

Using the financial manager application example described earlier in this book, we will look at how the balance might be displayed and updated. The diagram illustrated in Figure 26.8 shows the three elements of the MVC triad, the model (in this case an instance of statement - hence the use of statement in brackets to indicate we mean a statement and not a general type of model object), the view and the controller.
<figure><img src="image_112.png" /><figcaption>Figure 26.8: Tracing the interactions in the MVC</figcaption></figure>

The view is displaying a very simple window, which can display the current balance and a button labeled deposit. The controller is responsible for responding to the button click.

The sequence of message which would be sent between these objects as the window was created and a user interacted with the window are illustrated in Figure 26.8 and described below:

1. The statement object is instantiated and the view is opened. The view object must first draw the window. To determine the current balance it must send the message balance to its model (the statement). The returned value is then displayed in the output field.

The user clicks the mouse in the area of the screen used to display the button. The controller sees this click and enters into a dialogue with the view to determine if the click was actually within the button or not<fnref n="12" />. If it was, then the controller must send a message to the model to tell it to deposit ten pounds (we are assuming every deposit equals ten pounds for simplicity). This is done by sending the message:

```
model deposit: 10.
```

2. The model (a statement) receives the message deposit and records this. It then updates the current balance and sends itself a changed message, e.g.:

```
balance: newAmount
balance := newAmount
self changed: #balance.
```

3. Because the model sent itself the changed message, an update message is sent to its dependents, one of which is the view.

4. The view receives the update message. Its implementation of update runs the code used to create the balance view in the first place. That is, it sends the message balance to the model as in step 1.

There are a number of points worth noting about this example. Firstly, the view does not record anywhere what the actual balance is. It merely obtains the value from the model and displays it on the screen. From that moment on it forgets it. Secondly, the controller must ask the view to determine if the cursor is within the region of the button. That is, the controller does not know where on the screen the button is displayed, nor does it attempt to obtain that information from the view. Thirdly, even though the controller has direct access to the view, it does not tell the view what it is asking the model to do. The view is unaware of any change in the model until it is sent an update message. At this point it requests the current balance from the model. Note that this means that if the statement was sent a deposit message by some other object (rather than by the controller) it would still result in the view being told to update itself. Finally, the model is unaware that the message:

```
deposit: 10.
```

came from the controller. It could have come from any object and thus the model is completely insulated from the controller and the view.

<footnote n="12">¹² We will come back to this issue of which controller actually catches the input and which view is questioned about the position of the cursor at a later date.</footnote>
## 26.4 Views and subviews

In the example in the previous section, it is unlikely that the button would actually have been handled by the window controller or that the window view would have determined how it was displayed. Rather the button would have had its own ButtonView and associated ButtonController (indeed Figure 26.4 and Figure 26.5 suggest this). The ButtonView would have been a subview of the main window and would have been responsible for displaying the button and checking whether the mouse was over the button.

In fact views are designed to be nested. Most windows actually involve at least two views, one nested inside the other. The outermost view, known as the top component, manages the familiar window features (for example, the window menu bar etc.). It has an associated controller which manages the familiar moving, framing, collapsing and closing operations available from windowing environments.

Inside the top component are one or more subviews, known as components, and their controllers (remember almost all views have an associated controller) which manage specific elements of the view (e.g. buttons, scroll bars, selection boxes etc.). The subview (component) refers to the view it is an element of, as its container. Thus a subview is held within a container and a container possesses components (which are its subviews).

A component may, in turn, have additional components (although this is often not required). The container/component relationships are recorded in instance variables within the views. Each component has a link to its container and a container possesses an ordered collection of components. Thus each window's top component is the top of a hierarchy of components.

Typically, this means that when creating a window you first instantiate the top most view and then create and place subviews within the top level view. Figure 26.9 illustrates exactly this for a very simple window. This is a working example which you can type into a Workspace and evaluate.

The actual source code can be broken down into three sections. The first section creates a new `ScheduledWindow`. Scheduled windows represent the top connection to the host window system<sup>13</sup>. They are always the top of the view hierarchy (that is they are always the top component). Scheduled windows can have a label, a minimum and maximum size, can possess a single component (which can be made up of multiple views), possess a `StandardSystemController` (a controller specifically designed to work with scheduled windows) and of course a model. Having created the scheduled window, the code sets its controller, gives the window a label and specifies its minimum size.

<figure><img src="image_113.png" /><figcaption>Figure 26.9: Creating a simple window</figcaption></figure>

The second part of the code creates a composite part. A composite part is essentially a view which is made up of one or more subviews. That is, it is a collection of subviews and appropriate behaviour for handling these subviews<sup>14</sup>. In the example in Figure 26.9, two components are added to the compositePart. One is a very simple view which is a composed text. Composed texts allow strings to be displayed as a view. Note that it is the compositePart which determines where the 'Hello' will be

<footnote n="13"><sup>13</sup> "Scheduled" really relates to the fact that all `ScheduledWindows` are held by a control manager which determines (schedules) which of them is active at any one moment in time. Note only one window can be active for user input at any particular moment.</footnote>

<footnote n="14"><sup>14</sup> There is of course more to it than that, involving Wrappers and VisualComponents, however as these are essentially modifications of the basic MVC we shall leave an investigation of this issue to the reader.</footnote>
displayed. The second component added to the compositePart is another composed text (displaying the string Goodbye). However this time, the string is being bordered. That is, a box is being drawn around that string as a border. This border is actually handled by a **Wrapper** (Wrappers provide needed bookkeeping information such as translation, clipping, borders, etc.). Note that the border is specified relative to the size of the encapsulating window (this is why the rectangle specifying the border is specified as 0.2 by 0.3 to 0.5 by 0.6. This means that the top right hand corner of the border should start at a position which is 20% of the width of the window by 30% of its depth and should extend to a position which is 50% of its width and 60% of its depth (note windows have their zero, zero position in the top left hand corner of the window).

The third part of the source code in Figure 26.9 adds the compositePart (containing the two strings) to the scheduled window and opens the scheduled window. The result of opening the window is illustrated in Figure 26.10.

<figure><img src="image_114.png" /><figcaption>Figure 26.10: A simple window</figcaption></figure>

An important point to note is that although a view can contain multiple subviews which it coordinates, only the views are connected; the associated controllers are not. This is illustrated in Figure 26.11. Finally, views can only have one controller and one model. Controllers can also only have one view and one model. However, models may have any number of views associated with them.

## 26.5 The controller hierarchy

To determine which controller should respond to the user input, there is a controller hierarchy which mirrors the view hierarchy. At the root of this tree is the controller associated with the top component. This controller tries to find a sub controller which will accept control. If none will accept control then it must process the input. Controllers will only accept control if the cursor is within their view. Upon accepting control the first thing a controller will do is see if a subcontroller will accept control. Once a controller has control, it will retain control until the cursor leaves its view. Any input from the user will then be handled by the appropriate controller.

<figure><img src="image_115.png" /><figcaption>Figure 26.11: The view-subview / controller relationships</figcaption></figure>

The actual mechanism through which this is performed is slightly complicated, however, basically, whenever the cursor enters a window a control manager (see the class ControlManager for further details) passes control to that window. This is done by asking each window controller whether it wants to take control or not (via a message isControlWanted). The first controller that requests control is given control. This is done via the message startUp.

It is then up to the windows controller to decide how it will handle this control. Typically it determines which of its subcomponents wants to gain control via the message subViewWantingControl. The window (or top component) then asks its components whether they want control (using the objectWantingControl message). The components (or views) then ask their controllers whether they want control. If the controller identifies that it should have control, then it takes over the primary control operation.
## 26.6 Summary

In this chapter you have encountered the Model-View-Controller (MVC) architecture for the first time. You have seen the basic principles behind the construction of graphical user interfaces to applications and examined the concepts of the View, the Model and the Controller. Remember these are just the basics, not only is the situation much more complicated than indicated here for real world applications, it varies from dialect to dialect (and in some cases from version to version). Windowing systems in general have become very powerful, this means that very large books can be dedicated to explaining the minute of a particular language and its facilities and Smalltalk is no exception. So if you want to get to know more about how Smalltalk handles graphic windows, read the manuals, examine the classes and experiment. Enjoy!

## 26.7 Further reading

This chapter has only attempted to provide a very basic introduction. However, there are a number of useful places for you to look for further guidance. For example [Lalonde and Pugh 1991b]. This book goes into the user interface side of Smalltalk in great detail. Some parts of it are now out of date, however it is still an excellent reference. As always [Hopkins and Horan 1995] is an excellent reference. In particular see Chapters 29 to 34. You should also have a look at your system's manuals, for example, the following manuals supplied with VisualWorks are also very good references: VisualWorks User's Guide, ParcPlace-Digitalk, Chapters 18 to 20 and the VisualWorks Cookbook, ParcPlace-Digitalk.
# 27. Graphical User Interface Construction Tools

## 27.1 Introduction

This chapter provides a brief introduction to the VisualWorks window building facilities. The VisualWorks user interface builder is a tool which allows the developer to interactively construct a window using an object oriented drawing tool (à la MacDraw, xfig or AutoSketch). This drawing tool can then generate the Smalltalk source code required to actually create an instance of the window designed by the user. This Smalltalk window definition can then be easily and simply linked to a user's application. Thus making it particularly easy to construct graphical interfaces to Smalltalk applications.

This chapter is intended to provide a description of some of the features of the User Interface Painting tools. It is not intended to be a complete introduction to either the User Interface Builder or to the instance structure of VisualWorks windows.

In the remainder of this chapter we first consider what a window building tool is and then what window construction tools are available in VisualWorks (which are very similar to those tools in other Smalltalk development environments). We then consider the use of associated classes such as ApplicationModel and ValueHolder as well as how to construct windows using the available tools.

## 27.2 What is a user interface builder?

A user interface builder is a tool which allows a developer to construct a window by drawing it rather than by defining it programatically. This is a very great advantage as the construction of windows in many windowing systems is unnecessarily complex and difficult to understand. It often takes a great deal of source code just to create a window, give it a label, place an input field, an output field and a button on that window. In many situations the resulting "program" is difficult to maintain and may be error prone. The result is that it is difficult to build and modify windows, whereas windowing systems by their very nature are intended to be easy to use.

One approach to this problem was the construction of a window construction toolkit. TCL/TK is an example of such a toolkit [Ousterhout 1994]. It allows the user to specify the structure of a window in a simple scripting language. The resulting window can then be integrated with a program written in another language such as C. The problem with this approach is that firstly the developer must learn the TCL scripting language, secondly they must integrate the windowing system with their C programs (not always a straight forward task) and thirdly when a bug is encountered they must search through two separate systems to identify where the fault occurred. In addition this approach still relies on the developer laying out the window programatically.

Another approach is to use a window drawing tool. The motivation for such tools was to allow users to construct their windows graphically, enabling them to easily and quickly modify the window layout and then to compile the graphic window into source code. The source code could then be compiled to construct the window. In the early days of these systems it was necessary to integrate your application code with the source code generated by the window construction tool. Having done this, if you ever modified the window, you would overwrite any application code. Obviously this is not acceptable, and was caused because the window construction tools were not closely integrated with a development environment.

The age of the visual tool overcame this hurdle. Languages such as VisualBasic, Visual C++, Symantec's Visual Cafe and of course VisualWorks, allow a developer to draw a window on the screen, compile it, add their own application code and modify the window without any loss of information. These tools have greatly simplified the construction of graphical interfaces and enabled a far wider range of applications to benefit from sophisticated windowing environments.
## 27.3 VisualWorks window painting tools

<figure><img src="image_116.png" /><figcaption>Figure 27.1: The user interface builder and resource Launcher buttons</figcaption></figure>

The VisualWorks user interface builder is initiated using the canvas tool button on the VisualLauncher. This button has a picture of an easel with an artist's canvas on it (see Figure 27.1). The user interface builder is comprised of three tools. These tools are the *palette*, which contains the elements to be placed on a window, the *canvas*, which is the drawing area for the window and the *canvas tool*, which allows the user to issue specific commands such as the installation of a window.

The user interface builder in VisualWorks allows the user to create the window of an application from a wide range of visual components. These visual components are available from the Palette and include components such as buttons, text, sliders, tables and static visuals like rectangles and lines. Using these components the user can build up a window much in the same way as a diagram might be drawn in an object based drawing tool.

The user interface builder also provides a set of layout options in the canvas tool for relative and absolute positioning and sizing, alignment and grouping of objects. Again this is done in a similar manner to that of an object based drawing tool.

Figure 27.2 illustrates the window painting facilities being used to draw a modified VisualLauncher. On the left of the diagram is the Palette on which iconic versions of graphic objects are made available to the user. On the right of the Palette is the canvas on which the layout of the window is drawn. Additional tools are available which allow the user to specify the properties associated with the graphic objects, for example, it is possible to specify what action should be performed when a button is pressed etc. The Canvas Control is displayed above the canvas window. This window allows the properties of the canvas to be specified.

<figure><img src="image_117.png" /><figcaption>Figure 27.2: Creating a new Launcher using the window painting facilities</figcaption></figure>

It is also possible for the user to generate an actual working version of the window which has just been painted. This can be done by first *installing* the window. This actually generates a class definition for the window. However, this is only the first step towards generating a functioning window. It is then necessary to create the appropriate methods for displaying and updating values displayed in the window and to produce stub methods for any actions which should be associated with the graphic objects in the window. Such information can be entered by the user via the definer option in the canvas tool. This generates accessor methods for the variables referred to or stub methods for the actions entered earlier by the user. These stub methods must then be "filed out" with Smalltalk code using the standard set of browsers.
### 27.3.1 Palette

The Palette tool provides a set of ready made graphic components (or widgets) which can be placed on the canvas to form part of a window using a simple drag and drop method. This is illustrated in Figure 27.3 where a table component is being placed on a blank canvas.

The top two icons on the palette indicate the single component option (the left hand icon) and the multiple component option (the right hand icon). The multiple component option allows multiple components of the same type to be placed quickly and easily onto the canvas. For example, if you wish to place three buttons on the canvas, then either you have to select the button icon each time you have placed a button on the canvas, or you can select the multiple component icon and then the button icon. This then allows you to place as many buttons on the canvas as you require.

<figure><img src="image_118.png" /><figcaption>Figure 27.3: The Palette and the Canvas</figcaption></figure>

The remaining icons allow various component parts to be placed on the canvas, these are (from top left to bottom right): button, check box, radio button, textual or graphical label, input and/or output field, text editor field, menu button, list selection box, combo box (a menu and a button combination), horizontal or vertical divider, graphical box (with or without a label), rectangular or circular graphical region, slider, table, data set, notebooks, subcanvas (see later), view holder (see later chapter) and charts icon. The final icon indicates a graph browser (this is an example of a third party widget which is integrated with the palette).

### 27.3.2 Canvas

The canvas is the drawing area of the user interface builder (see Figure 27.3). In effect it is the window which will be displayed to a user. The developer can place graphic components on the canvas, move them around, give the canvas a label and define its size, background color and foreground color. For further details on how to do these operations see the VisualWorks manuals.

### 27.3.3 Canvas Tool

<figure><img src="image_119.png" /><figcaption>Figure 27.4: The Canvas Tool</figcaption></figure>

The canvas tool (illustrated in Figure 27.4) provides a range of facilities which can be used in conjunction with the current canvas. These facilities can be divided into three: widget layout control, window and widget properties and window specification and construction. Each of these will be considered separately below.
### 27.3.4 Widget layout control

The widget layout control buttons are presented across the top of the canvas tool window. The first six buttons control widget alignment, the next four control widget distribution and the last two control widget size. Each of the operations is relative to the first widget selected. For example, the first button will align all the currently selected widgets such that their tops are all in line with the very first widget selected.

### 27.3.5 Properties, aspects and actions

The properties button on the canvas tool brings up the properties tool. This tool displays the information appropriate for the selected widget. If no widget is selected then the window details are selected.

<figure><img src="image_120.png" /><figcaption>Figure 27.5: The Properties tool</figcaption></figure>

The properties tool allows the user to specify a wide range of details about a widget. For example, it is possible to specify any associated colors, position, etc. The precise details of what can be defined depends on the particular widget.

Figure 27.5 illustrates the properties tool for an action button. In Figure 27.5 the developer has specified that the selected button should have a label 'Add' (this is a textual label but equally the label could be a graphic image) and the *action* which is the symbol `#doAdd`. The action is the name of the message which will get sent to the object displaying the window when the button is pressed. The developer therefore defines this method to specify the add buttons' behavior.

In a similar manner other widget's details are defined using the properties tools. For example, for an input/output field the tool would request the field's name, and whether it should be output only or input and output (buttons and input/output fields are probably the most common widgets that you will use). The name of the input field is referred to as its *aspect*. Essentially it is the name of an instance variable which will be used to hold the field's data. Other common widgets are the list widget which displays the contents of a list and table widgets which display data held in tabular form. For further details on the properties tool see the VisualWorks manuals.

## 27.4 Window specification and creation

Once the developer has designed the window to their satisfaction you can install it onto a class (essentially this means that you can compile it into Smalltalk). This is done using the 'Install' button on the canvas tool. This button triggers the installer (illustrated in Figure 27.6). The developer must then specify the name of the class to `install` the window onto. If the class does not already exist it will be created by the system. In such a situation the developer must select what category to place the class into and what the superclass of the class will be.

In almost all circumstances the superclass of the new class will be `ApplicationModel`, or one of its subclasses. `ApplicationModel` is an abstract class that provides the functionality required to
build a running user interface from the output of the user interface builder. Therefore by inheriting from `ApplicationModel`, the new class (called ` ToDoOrganiser` in Figure 27.6) is able to create user interfaces.

You may note that in Figure 27.6 I also specified a 'Selector' called `windowSpec`. This is actually where the window specification will be placed. The selector is actually the name of a class side method defined within a class protocol called `interface specs`, which returns a `windowSpecification`. This is actually an array of widget specifications. This approach allows different windows to be defined for the same class and saved under different names. For example, we could construct a welcome window, an input window and an output window for some class and call each of them by different selector names. We could then choose which window we wished to open using the `openInterface:` message. Note that by default it is the window defined by the specification held in `windowSpec` which is created in response to an open message. Therefore:

* `a ToDoInterface open`. This opens a window defined by the `windowSpec` class side method.

* `a ToDoOrganizer openInterface: #welcome`. This opens the window defined by the `welcome` class side method.

Once the window has been installed onto a class you now have the potential to create a graphical application.

<figure><img src="image_121.png" /><figcaption>Figure 27.6: The Installer</figcaption></figure>

## 27.5 Application models versus domain models

In the last chapter we talked about the MV C architecture and that the model was the element of the MVC which held the data. However, in this chapter we have introduced a new class called `ApplicationModel` (which if you are very observant you will have noticed in the last chapter was a subclass of M odel). So where does that leave the good old MVC? Is the `ApplicationModel` the original model from the MVC or is it something different?

In fact when we talked about the MVC we did actually state that there may be very many objects involved in providing the functionality of the whole system, but that only one of them might act as the model in the MVC. Essentially, the use of an explicit `ApplicationModel` class is really acknowledgment of this. By creating a class which is intended to provide the behavior necessary to create and manage the graphic user interface the developer can encapsulate all the user interface functionality they need in subclasses of this `ApplicationModel`.
<figure><img src="image_122.png" /><figcaption>Figure 27.7: Using an ApplicationModel with an domain object</figcaption></figure>

The objects involved in providing the applications functionality (or domain model) no longer need to be involved in the model hierarchy, they can inherit from any class in the system. For example, if we were to link our class *Statement* into this architecture we would do so as indicated in Figure 27.7. In this figure the classes are indicated by rectangles and instances by round cornered boxes.

The approach of separating out *ApplicationModel* functionality is extremely powerful as we can now develop the user interface and the system functionality completely separately. The following table summarizes this separation.

<table><tr><td>application model</td><td>Provides user interface processing capabilities</td></tr><tr><td>domain model</td><td>Provides system functionality</td></tr></table>

The *ApplicationModel* class is actually the root of its own application model hierarchy. Figure 27.8 illustrates part of this hierarchy. As can be seen from this diagram many of the graphical tools provided within VisualWorks are subclasses of *ApplicationModel*. For example, the user interface builder is provided by class such as `UIBuilder`, `UIBuilderWatcher` and `UI Palette`. The browsers are subclass of *ApplicationModel* as is the inspector, the changes tool and the file browser. The graphical class browser used to display the class hierarchies is also a (user) defined subclass of *ApplicationModel*.

<figure><img src="image_123.png" /><figcaption>Figure 27.8: Part of the *ApplicationModel* hierarchy</figcaption></figure>

## 27.6 Defining a window's functionality

We return now to the process of creating a window. So far we have defined the structure of the window but not yet how information is made available to the window (or obtained from the window), nor what happens when buttons are pressed etc. We have however defined the aspects for input fields (their
names) and the actions for buttons (the messages to send if they are selected). We can now get the system to define these for us automatically. This is done using the 'Define' option from the canvas tool. This brings up the definer window as illustrated in Figure 27.9. This allows the user to select which aspects and which actions they wish to define. This can be used to ensure that modifications made to the definitions by the developer do not get over written.

<figure><img src="image_124.png" /><figcaption>Figure 27.9: The Definer</figcaption></figure>

Different things happen to input fields (and to lists and tables) than to action buttons. In the case of an input field the system defines an instance variable on the class and creates an accessor method as illustrated in Figure 27.10. This accessor method also provides a lazy initialization approach to the instance variable.

For an action the definer merely creates a stub method which returns self. This ensures that when the window is created an exception is not generated when a button is pressed. The user is then able to redefine the action methods to perform the desired operations.

<figure><img src="image_125.png" /><figcaption>Figure 27.10: The defined entry aspect</figcaption></figure>

## 27.7 Initialization

It is important when using an application model to ensure that any initialization performed does not overwrite that accomplished higher up in the `ApplicationModel` class hierarchy. For example, in Figure 27.11 we define an initialization method for the simple to do list Organizer presented in Figure 27.12. The first thing that this method does is to send a message `initialize` up the class hierarchy using:

super initialize.

This ensures that the initialization steps performed by the `ApplicationModel` will be carried out first. This is essential because if `initialize` merely overwrote the inherited method, then the user
interface builder would be unable to create the user interface window (this is actually a common mistake even for those used to the VisualWorks system).

<figure><img src="image_126.png" /><figcaption>Figure 27.11: Initializing an application model</figcaption></figure>

The remainder of the method in Figure 27.11 can then initialize the application specific aspects of the subclass of `ApplicationModel`. In this case it initializes an instance variable called `toDoList` and a value holder<fnref n="15" /> on a string for an instance variable `entry`. Finally it constructs the selection list displayed on the left hand side of Figure 27.12 and stores it in the `todoTable` instance variable.

<figure><img src="image_127.png" /><figcaption>Figure 27.12: The working interface</figcaption></figure>

## 27.8 Resource Finder

The Resource Finder (also known as the Finder) is a navigation aid for developers. It is intended to help developers to find, edit, delete and execute resources such as windows and menus. Figure 27.13 illustrates the VisualWorks Finder. The left hand selection window presents application classes, while the right hand selection window indicates the resources defined for the selected application class. There are various filter options which can be used to reduce the number of application classes displayed. The filters can be accessed by selecting the classes sub-menu from the view menu.

Figure 27.13 illustrates the resources defined for the `VisualLauncher` class (the class which is used to display the VisualWorks Launcher window). As can be seen from this example, an application can have more than one window specification (in this case it has two: `windowSpec` - the default window specification and `aboutDialogSpec`). If when one of these is selected the user selects the

<footnote n="15">¹⁵ We will come back to value holders later in this chapter.</footnote>
Edit button, then the user interface builder is Launcher for the given specification. If the Start button is selected then an instance of the application class is created and opened on the specified specification.

<figure><img src="image_128.png" /><figcaption>Figure 27.13: The Resource Finder</figcaption></figure>

The Resource Finder is a useful way of finding the specifications provided for various classes, menus, starting applications and editing existing applications.

## 27.9 ValueHolders

In VisualWorks the biggest departure from the original ParcPlace version of Smalltalk, which was known as Smalltalk-80 and then ObjectWorks, is the use of *ValueHolders*. ValueHolders represent a modification to the way information is exchanged within the MVC architecture. This modification is intended to further buffer the user interface from the application model. The idea is that the model should present only that *update*: a data structure and its associated methods. However in the MVC architecture, information about the interface often crept into the model. For example, the model would have to send the change message to itself at the right times and make the appropriate information available to the view (when the view received the resulting *update*: message). The use of ValueHolders is an attempt to remove this concern from the model.

<figure><img src="image_129.png" /><figcaption>Figure 27.14: The modified MVC architecture in VisualWorks</figcaption></figure>

### 27.9.1 How they work

The *ValueHolder* acts as an intermediate object which buffers the application model from the actual objects it maintains. The model now refers to *ValueHolders*, which refer to the actual objects being modeled (this is illustrated in Figure 27.14). Thus the model does not make direct reference to other objects, instead it refers to a *ValueHolder*. When the model wants to access a value it requests that the *ValueHolder* provides it. Similarly, if it wants to update a value it sends a message telling the *ValueHolder* to update its value.

When the object referred to by a *ValueHolder* changes, it is the responsibility of the *ValueHolder* to inform the associated view that its value has changed and that the view should display this new value (in the original MVC it was the responsibility of the model). Similarly, if the controller receives input from the user which directly changes the value of the *ValueHolder*, the controller merely informs the value holder that its value should change.
While this may seem to be a complicated (and rat her convoluted) way to change the value of part of
the model, it has many advantages in flexibility and modularity. No longer does the model have to
inform the interface (view) about any updates; the `ValueHolder` does it automatically wh enever the
value it holds changes. Indeed, it is no longer necessary for the model to concern itself with any aspect
of the view (or controller) at all. The model now really is separated from the view and controller. This
makes the task of developing highly graphical systems much easier.

### 27.9.2 Working with value holders

If the user interface builder described above is used to construct a window and the definer has been used to generate the instance variables and accessor methods for the windows aspects, then valu e holders for these instance variables will automatically be created. However, it is still possible to do this manually (and may be used with non interface instance variables).

A new value holder can be created in two ways:

1. By creating an instance of the class `ValueHolder`. For example,
   `balance := ValueHolder with: 230.`

2. By converting an object to a value holder and object. For example,
   `balance := 230 asValue.`

Whichever approach is used, the contents of the value holder is accessed and up dated in the same way. Accessing the valueholder's contents is performed using the `value` message and updating it is performed using the `value:` message. For example:

```
currentBalance := balance value.
balance value: (currentBalance + deposit).
```

If a new value is assigned to a value holder the `value:` message *must* be used, otherwise the value holder will be deleted and the link to a window (if present) and to any dependents will be lost.

## 27.10 The `onChangeSend:` message

In an earlier chapter we discussed the use of the dependency mechanism as a means of informing interested parties about a change in the value of something. Value holders take this concept one step further and makes it more explicit. Whenever the value of a value holder is modified using the `value:` message a check is made to see whether there are any interests recorded on that value holder. If there, then the associated action is performed.

The interest in a value holder is registered using the `onChangeSend: aSymbol to: anObject` message. This message states that when the value holders value changes (via `value:`) the symbol is sent to the object as a message. A common use of this message is to ensure that some action is performed whenever the user changes a value currently being displayed. For example:

```
balance ChangeSend: #checkInTheRed to: currentAccount
```

states that when the value holder held in `balance` is modified, the message `checkInTheRed` should be sent to the object held in `currentAccount`. Note that unlike the version of the dependency mechanism discussed earlier, this approach explicitly states what action should be performed on what object when a particular value changes.

If at a later date the dependency between the value holder and the message send to the specified object should be retracted, the (less meaningfully named) `retractInterestsFor: anObject` message can be used.
## 27.11 Visual reuse

The aim of visual reuse is to avoid the necessity to rebuild applications from scratch. There are essentially three types of visual reuse in VisualWorks, these are: *cut and paste* between windows, the use of *subcanvases* and the use of *inheritance*. Each of these will be discussed briefly below.

### 27.11.1 Cut and paste reuse

It is possible to cut and paste widgets from one window to another using the canvas and the copy edit menu option. Essentially you open the user interface builder on a particular window, select the elements of the window that you wish to copy, use the edit menu to copy them and then go to another canvas and use the edit menu option paste, to place them on the new window. This copy operation also copies all the preference information defined for the first window (although it does not copy any instance variable definitions, initialization or accessor methods). All that is now required for these widgets to be available on the new window is to define them and carry out any initialization operations required.

This approach saves time on building new windows as whole window layouts (such as buttons, input fields, test labels, text boxes etc.) can be copied at once. It is also possible to mix widgets copied from a number of different windows.

However, this approach suffers with problems of maintenance (for both window layout and source code). For example, if the purpose of copying a set of widgets was to ensure that all windows had a similar look (for example, with the same set of buttons across the bottom of the window for operations such as next, last, quit and help). Then whenever a change was made to one window, the same change would have to be performed for every window in the system. Similarly, if the windows were on different classes it would be necessary to ensure that any source code changes were reflected in each class.

Many early graphical user interface building tools provided only this sort of reuse. Indeed there are many systems still in use which provide only this level of support.

### 27.11.2 Subcanvas reuse

Each window is actually a canvas which has certain properties including the windowSpec. These canvases are by default used to construct the window. However, the layout of part of a window can be defined by a different specification. The top level window handles this by treating the lower specification as a subcanvas. That is a subcanvas takes its layout from a different window specification from that of the result of the window.

There are in fact two ways in which a subcanvas can be used. These are specification based and instance based. We will consider each of these separately.

<figure><img src="image_130.png" /><figcaption>Figure 27.15: Subcanvas reuse</figcaption></figure>

**Specification based reuse.** Specification based reuse uses another window specification (in addition to the current window specification) to define what the area of the window controlled by the subcanvas should look like. This subcanvas can be supplied by another application model (by referencing the other class). This is indicated in Figure 27.15(a). In this situation, the window's application model must provide the necessary functionality required by the widgets in the subcanvas area.

**Instance based reuse.** Instance based reuse differs from specification based reuse in that in addition to being able to obtain the window specification used to determine the window layout of the subcanvas from another class, the functionality of the widgets is handled by an instance of that class. Thus the subcanvas now relates to a completely separate object from the remainder of the window. This is indicated in Figure 27.15(b).
Instance based reuse is more complicated to achieve but has the advantage that the required functionality is also obtained.

### 27.11.3 Inheritance of canvases

Subcanvas reuse as described above really relates to *part-of* relations hips and must be redefined for each window which wishes to use the same subcanvas even if all the windows relate to subclasses of a common ancestor class.

<figure><img src="image_131.png" /><figcaption>Figure 27.16: Inheritance of subcanvases</figcaption></figure>

One way of alleviating this duplication is to use inheritance with the reuse of parts of a graphical user interface. For example, rather than obtaining the subcanvas specification from another class, the subcanvas specification is inherited from a parent class. This is illustrated in Figure 27.16.

This enables not only part of the window layout to be inherited, but instance variables, accessor methods and value holder relationships etc. This can be done by specifying the inherited window specification containing the required layout, in the `canvas` property of a subcanvas widget.

## 27.12 Method of working with the UI builder

At this point it is worth noting the sequence of steps (and their order) which are generally taken when developing a window using the user interface builder. We will assume that we are constructing a new window on a new class. The only differences that you need to bear in mind if this is not the case is to ensure that you don't over write existing window specifications or method definitions (unless that is what you intend to do).

1. Open the user interface builder using the `canvas` icon on the Visual Launcher and draw the desired window.

2. Once you have drawn the window, select **Install** from the `canvas` too. 1. This will bring up the installer window (illustrated in Figure 27.16) with an empty class name. You must enter a class name before you can continue.

3. Having specified a class name the window illustrated in Figure 27.17 will be displayed. As we are defining a new window we select the *Application* option in the *Define As* grouping which results in the `ApplicationModel` class being selected as the super class of our newly defined class. If we wish the class to be defined in a category other than `UIApplications-New`, then we also need to specify the category (if this does not already exist it will be created). We can now select **OK**.

4. This returns us to the installer where we have the option of specifying a window specification name other than `windowSpec`. Remember `windowSpec` will be used as the default window layout when a window is opened. This is done by typing in a new name into the box below the prompt saying "or enter new Selector".

5. We are now ready to define any action methods, accessor method etc. for the window. This is done using the **Define** button on the `canvas` tool. This causes the definer window to be displayed (as illustrated in Figure 27.9).

6. You are now ready to define any additional initialization code required. Once this is done you can start the window using the **Open** button on the `canvas` tool.

7. Any subsequent editing of the window follows a similar pattern. However you will not be prompted for the superclass nor category of the class again.
<figure><img src="image_132.png" /><figcaption>Figure 27.17: Defining the parent class and category</figcaption></figure>

## 27.13 Summary

In this chapter you have learnt about the VisualWorks window construction tools their use and the concept of value holders. You have also been told about the modifications introduced in VisualWorks to the basic MVC framework and the difference between application models and domain models.
# 28. A Visual Organizer

## 28.1 Introduction

This chapter presents a VisualWorks version of the `Organizer` Class described earlier in the book. That is, a graphical front end is constructed that works with the classes previously constructed. The organizer was intended as an electronic personal organizer. It therefore possessed an address book, a diary (or appointments section) and a section for notes. However the version previously described required the user to send the appropriate messages to an instance of `Organizer` using the Workspace. For example, in Figure 28.1 the user has created an instance of `Organizer` and sent it a variety of messages which record addresses, appointments and notes. This certainly works, however, the use of a graphical interface would be preferable. This would allow the user to input the appropriate information via buttons, input fields and text windows.

<figure><img src="image_133.png" /><figcaption>Figure 28.1: Using the (non graphical) Organizer</figcaption></figure>

Figure 28.3 illustrates the type of interface to be constructed for the address input window. As can be seen from this figure, having a graphical user interface (GUI) leads to a far more intuitive interface.

The chapter is structured in the following manner: Section two describes the `VisualOrganizer` class which acts as the class used to define the graphical interface, Section three describes the associated `AddressBook` class and Section four provides a final comment.

## 28.2 VisualOrganizer class

In the example in this chapter we are going to construct a graphical version of the `Organizer` we constructed earlier in this book. We shall make a number of changes to the architecture of the `Organizer` in order to define the `VisualOrganizer`. The major changes are:

1. The `VisualOrganizer` class will be a subclass of `ApplicationModel` rather than `Object`. This is because we wish to inherit all the facilities used to manage VisualWorks windows. This is
important, as these facilities handle everything from creating the window to handling user interaction (e.g. input and output).

2. The other major change is that we have broken the **Organizer** class down into its constituent parts. i.e. we now have separate classes for the address, appointments and notes functionality. the **Organizer** class now acts as a composite class which obtains its functionality from the instances it will possess.

The **VisualOrganizer** now works by displaying a Launcher window when the **VisualOrganizer** is sent the message open. This message is like new except it not only creates a new instance of a class, it also causes that instance to open whatever window is defined in the default window definition method. This method is called windowSpec and is maintained on the class side. The **VisualOrganizer Launcher** is illustrated in Figure 28.1.

## 28.2.1 Constructing the Launcher

First of all we need to define the class category we are going to put our classes in. The category will be called 'Visual Organizer Classes'. If you wish to follow the example in this chapter yourself, you should create this category now.

Next we will define the layout of the VisualOrganizer Launcher window. To do this we use the VisualWorks User interface builder. As we are creating a completely new application you should launch the user interface builder from the VisualWorks Launcher using the easel icon (if you are unclear on what the user interface builder does see the last chapter).

Having launched the user interface builder, the first thing to do is to give the window as a whole a label. This can be done using the properties option available from the right mouse button menu (or middle if you have a three button mouse). Note that the properties window will display the properties of the selected widget or the window as a whole if no widget is selected.

I have chosen to use the label "Visual Organizer" for my window, however you can use whatever label you feel is most appropriate as the label is not significant for the operation of the system. Once you have provided a suitable label select accept and close the properties window. Next resize the canvas as appropriate. You are now ready to begin constructing the Visual Organizer Launcher.

The window layout for the Launcher is illustrated in Figure 28.2. It shows that four buttons have been placed on the window. The text boxes with arrows indicate the action properties assigned to each button.

<figure><img src="image_134.png" /><figcaption>Figure 28.2: Defining the actions for the Launcher's buttons</figcaption></figure>

Each button is a basic action button with a textual label rather than an icon. Place each button on the window using the palette as indicated in Figure 28.2. Remember you can use the button widget with the multiple placement option (the box in the top right hand corner of the Palette) to place more than one button. Then use the properties tool to ensure that the button properties match those in the diagram.

The Exit button also possesses a number of look preferences. These are set using the **Color** option in the properties tool. The actual colors selected are:

* Foreground color: **white** and Background color: **Royal Blue**

* Selection Foreground Color: **Pale Blue** and Selection Background Color: **Red**

The first two colors are used to display the button on the window. The Foreground color relates to the color in which the text on the button is displayed and the background color the is the main color of
## 28.3 The AddressBook class

### 28.3.1 The AddressBook window

<figure><img src="image_135.png" /><figcaption>Figure 28.3: The layout and definition of the AddressBook window</figcaption></figure>

Figure 28.3 illustrates the layout of the AddressBook window. As can be seen it has two input fields as well as three buttons and two text labels. The specifications for these different widgets are indicated in the figure. Using the palette and the properties tools define the window following the steps outlined above.

For the window as a whole I have used the label "Address Book" however as before you can use whatever label you feel appropriate. The three buttons along the bottom of the window will be referred to these as input, query and exit (from left to right).

Once you have defined the layout of the window and the various properties you are ready to install the window on a class. To do this select the **Install** button from the Canvas Tool window and install the window on a class called **AddressBook** which is a subclass of **ApplicationModel**. Don't forget to change the category to "Visual Organizer Classes" otherwise it will be placed in the default category. Once you have installed the window onto a class you can select the **Define** option in the Canvas Tool window to define the instance variables and accessor methods for the two aspects (input fields) and the actions for the buttons (a.k.a. the method to run when the button is clicked). You are now ready to define the functionality of the AddressBook class.

### 28.3.2 The AddressBook class definition

In the System Browser, have a look at the class definition for **AddressBook**. You will see that a full class definition has been generated for you by the User interface builder. You now need to add the instance variable specific to the functioning of the class (rather than the instance variables specific to the user interface). This variable will be called **addressBook**. Once you have done that, your newly created class definition should look like:

```
ApplicationModel subclass: #AddressBook
instanceVariableNames: 'name address addressBook '
classVariableNames: ''
poolDictionaries: ''
category: 'Visual Organizer Classes'
```

Don't forget to accept the class definition. The class comment is left as an exercise for the reader (you must get use to defining them). You should also note that when you selected the **AddressBook** class there were two method protocols defined for you already. These were 'aspects' and 'actions'. The 'aspects' hold the instance variable access methods and the 'actions' hold the methods which will be run when the buttons are clicked.
### 28.3.3 The “aspects” protocol

The next thing we will do is to look at the methods which have been defined for us by the User interface builder in the “aspects” protocol. If you examine this protocol you should find two methods defined. One called `address` and one called `name`. If you examine these methods you should find that their definition matches those presented below:

**address**

"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."
```
^address isNil
    ifTrue: [address := String new asValue]
    ifFalse: [address]
```

We shall stop for a moment and consider what this method actually says. The method possesses one expression, the result of which will be returned when the method completes. The value will returned is dependent on the result of the `isNil` test. If the contents of the instance variable `address` "is nil" then the `ifTrue:` clause will execute, if not then the `ifFalse:` clause will execute. We shall take the false case first. If `address` does not contain `nil` then the value of `address` is returned by the `ifFalse:` clause. However, if the value of `address` is `nil`, then the assignment expression in the `ifTrue:` clause is executed. This assignment expression creates a new instance of the class `String`. It then sends the message `asValue` to this new string instance. This creates a value holder around the string. This *value holder with string* construct is then assigned to the instance variable `address`. The result of this expression is the value of assignment which is returned.

Thus, if the `address` instance variable has not yet been set (indicated by the value `nil`) an appropriate value for it is generated, otherwise its value is returned. This form of expression is referred to as *lazy initialization*. That is, `address` is initialized appropriately when it is required, rather than when the system is initialized. This can be useful sometimes, however it does mean that every time the value of `address` is obtained an extra expression must be considered (i.e. `isNil`). This means that is less efficient than initializing the value of `address` appropriately in an `initialize` method. The accessor method for the instance variable `name` is defined in a similar manner.

### 28.3.4 The “initialize” protocol

Now let us define the “initialize” method protocol. This method protocol will only possess one method, `initialize`. This method is presented below. It instantiates a `Dictionary` object to use with the `addressBook` instance variable. Notice that once again we do not access the instance variable directly. Instead we use an `updater` method.

**initialize**

"This method is called whenever an instance of `Organizer` is created"
```
| adBook |
"ApplicationModel defines its own initialize so send a message to super"
super initialize.
"Next we set up the address book instance variable"
adBook := Dictionary new.
self addressBook: adBook

As we are currently using lazy initialization with the 'aspect' methods `name` and `address` we have not initialized them here. However, as was indicated above, it would be more efficient to do so. However, it must be remembered that they are "aspect" variables rather than plain instance variables. This means that for the windowing operations to work correctly they must contain a value holder, which acts as a wrapper around the actual value they represent (see the last chapter for more details).

A common mistake (and the cause of much frustration) is to initialize the aspects in an `initialize` method as a `String` or a `Number` (with no value holder). This means that the "aspect" method `isNil` test fails and the `String` or `Number` etc. is returned. The problem is that this is not a value holder and thus cannot respond to input and output properly. Often this manifests itself when values fail to update themselves or updates from the user fail to propagate to the instances etc. Thus appropriate initialization should follow that used in the aspect methods, e.g.

```
address := String new asValue.
name := String new asValue.
```
The aspect methods can then be simplified to just return the contents of the associated instance variable.

### 28.3.5 The “actions” protocol

Another set of methods defined by the User interface builder are the “actions” methods. These are in the “action” protocol. We have already seen examples of these in the `VisualOrganizer` class. As you saw there, by default, these methods are defined to return the value of self. We therefore need to define them.

We shall first look at the `doExit` method as this is the simplest method. This method will close the window. To do this we again use the inherited `closeRequest` method. We therefore merely need to send the message `closeRequest` to self.

**doExit**

"This method closes the associated window"
self closeRequest.

Next we will look at the `doInput` method. This method takes input from both the name input field and the address input field and stores them using the `newAddress:for:` method which we will define later. Notice that once again we use an intermediate updater method to actually access any instance variables (this is good Smalltalk style). The `doInput` method is presented below.

**doInput**

"The method is executed when the input button is pressed"
| aName anAddress |
aName := name value.
anAddress := address value.
self newAddress: anAddress for: aName.

Notice that we do not just access the `name` and `address` aspects (instance variables) and save them into the temporary variables `aName` and `anAddress`. Instead, we send the message value to each of the aspects first. This is because, if we just took the contents of `name` and `address` we would obtain a `ValueHolder` object. What we really want is the contents of the value holder. To get this we must send the message value to the value holder. Thus `name value`, will return the value held by the value holder in the instance variable `name`.

Remember when you type this method in and accept it, the system will notify you that the method `newAddress:For:` is undefined. We will define it later!

Next we will examine the `doQuery` action method. This method accesses the `name` input field and updates the `address` input/output field. Again we must use the message value to access the contents of the `name` value holder. We then use the `addressFor:` accessor method (which we will define below) to obtain the address associated with the `name`. If the address retrieved is not `nil` then we put the address retrieved into the `address` input/output field. If it is `nil` we display an okay dialog with an appropriate warning message.

**doQuery**

"The method is executed when the input button is pressed"
| aName anAddress |
aName := name value.
anAddress := self addressFor: aName.
anAddress isNil
    ifTrue: [Dialog warn:'There is no address for ', name value.]
    ifFalse: [address value: anAddress asText.]

We will now examine the last statement in the method for a moment. This time we used the message `value:` rather than the message value with the value holder in `address`. This is because we were updating the contents of the value holder rather than accessing it. Thus the address value holder is set to the value of the parameter sent with the message `value:`. This parameter was actually the string returned by the `addressFor:` method. However, to be displayed it must be converted into a `Text` object (which understands how to display strings). This is achieved by sending the string in `anAddress` the message `asText`. This is necessary because the text editor field assumes that it will display a text (which has special properties such as font and style) rather than just a plain string. When
we access the value holder using value, it knows to return the string held by the text object within the value holder. But when we update the value holder we need to wrap the string in a text object.

### 28.3.6 The “accessing” protocol

Next we shall define the methods in the “accessing” protocol. There are four methods in this protocol. We shall first consider those associated with setting and updating the address book dictionary. The first of these is used to initialize the instance variable `addressBook` and the second to add new name and address associations to the `addressBook`. These are `addressBook:` and `newAddress:for:` respectively. The `addressBook:` method is very straight forward and is presented below.

```python
addressBook: aDictionary
    "This is an update method for the addressBook instance variable. It is used to
    accept a new dictionary object to use for the addressBook. It is intended only for
    use with the initialization method of the AddressBook class."
addressBook := aDictionary
```

The `newAddress:for:` method takes two parameters, the new address and the name. The method uses two different `Dictionary` methods. The first is used to check to see if there is already an `addressBook` entry with that name. We could not use the basic `at:` message as that generates an error if the key provided with the `at:` message is not present in the dictionary. However, the `at:ifAbsent:` message allows the code block provided with the `ifAbsent:` parameter to be run if the key is not present. In our case we do not want it to do anything other than return `nil`. By default when a block is evaluated it returns `nil` if nothing else is returned. We therefore only need to provide any empty block which will always return the value `nil`. We can then test the value of the temporary variable `alreadyThere` to see if it is `nil`. If it is `nil` then we can add the new name and address to the dictionary held in `addressBook`. If it is not `nil` we can warn the user that an entry with that key already exists using a dialog window.

```python
newAddress: anAddress for: aName
    "This method is used to add a new address to the address book."
    | alreadyThere |
    alreadyThere := addressBook at: aName ifAbsent: [].
    alreadyThere isNil
        ifTrue: [addressBook at: aName put: anAddress]
        ifFalse: [Dialog warn: 'That key is already present']
```

We shall now consider the last two methods in this protocol. These methods are `addressBook` which returns the contents of the `addressBook` instance variable and `addressFor:` which returns the address associated with a particular name (if one is present). The `addressBook` method is:

```python
addressBook
    "This is an access method for the addressBook instance variable"
    ^addressBook
```

The `addressFor:` method is slightly more complex as it must handle the situation where an address is not available (it uses the `at:ifAbsent:` message to do this).

```python
addressFor: aName
    "This method is used to retrieve an address from the address book."
    | anEntry |
    anEntry := addressBook at: aName ifAbsent: [nil].
    ^anEntry
```

### 28.3.7 A working application

If you have followed all the steps above correctly you should now have a working application. To start the application, type the following into a Workspace and evaluate it:

```
VisualOrganizer open
```

This will display the window illustrated in Figure 28.2. Now select the `Addresses` option and you should see a window such as that displayed in Figure 28.3. You can now type in a few names and addresses selecting input between each. Next try out the query option by typing in a name and selecting query. If
the name is in the address book, it will be displayed in the address book field. If not a warning message
will be displayed.

## 28.4 Summary

You have now created a VisualWorks GUI application. This application provides you with the basics of an address book. Of course, if you quit from the window you will lose all the names and addresses you have input. We will look later at how you can store the dictionary used for the names and addresses into a file so that you can access it again. The method we will use is called the Binary Object Streaming Service (or BOSS for short). It is better than saving straight ASCII, as it perseveres the objects rather than just plain text (where you would have to reconstruct the dictionary from the text).

An important point to consider is how we have structured this application. We have effectively bound the address book functionality into the user interface. This is not particularly good style, however for such a small application it seemed acceptable. A better structure would have been to construct a graphical interface which used the facilities defined in the original `Organizer` class.

## 28.5 The visual Financial Manager application

This is an exercise for you the reader. This application builds on the `FinancialManager` you have been constructing at various times throughout this book. The aim of this exercise is to provide a graphical interface to this application. The graphic interface should allow the user to:

1. Add deposits to the account for a specified amount.

2. Make payments (withdrawals) from the account for specified accounts.

3. Get the current balance and print a statement of all payments and deposits.

You should define the window independently of the `FinancialManager` class. This means that you can make the `GUIFinancialManager` class a subclass of `ApplicationModel`. You should then provide an instance variable in which the actual `FinancialManager` object will be held. This could be done in an `initialize` method. I have assumed that the two input/output aspects are `amount` and `balance`. These could also be initialized in this method. For example:

```
initialize
    super initialize.
    account := FinancialManager new.
    amount := 0.00 asValue.
    balance := 0.00 asValue.
```

In the above example, `account` is an instance variable used to hold the `FinancialManager` object. Note that we must first send the message `super initialize` to ensure that the inherited initialization is performed.

It should now be possible to write methods to handle user inputs in the form of button clicks which pass the appropriate information onto the object held in account. For example (Note this assumes that the amount to be input field is called "amount"):

```
deposit
    account deposit: (amount value).
```
# 29. Using a View Within a Window

## 29.1 Introduction

This chapter describes how a custom view can be incorporated into the type of window seen in the last two chapters. This is important because although the user interface builder is extremely good at creating buttons, input/output field style windows, it cannot be used to display graphical information. For example, if you wish to construct a graph of nodes to illustrate a particular route in a path finding application then this must be generated using the basic MVC (Model-View-Control) features.

In this chapter we consider a simple drawing application which we will call SmallDraw . This application is illustrated in Figure 29.1.

<figure><img src="image_136.png" /><figcaption>Figure 29.1: The SmallDraw application</figcaption></figure>

SmallDraw allows boxes, circles and points to be placed on a scrollable drawing. The three widget buttons and the exit button have been defined using the user interface builder. The scrollable drawing area is a scrollable view which has been created by the user interface builder but which is controller by a separate model, view and controller.

In the remainder of this chapter we will consider how this application was constructed.
## 29.2 The custom view widget

### 29.2.1 What is a custom view widget?

Any widget displayed in a window created using the window building facilities of the canvas, the palette and the canvas tools uses a view to display itself. This view determines what will be displayed, what the associated view does and how it links with your application. However, not everything you will wish to do is covered by the widgets provided by the palette. For example, if you wish to display a network of nodes, then there is no built in widget to do this - you must write the code which will display such a network using a custom view.

<figure><img src="image_137.png" /><figcaption>Figure 29.2: The View Holder Palette icon</figcaption></figure>

A custom view is held within a view holder which can be placed onto a window using the user interface builder. This is done using the view holder icon which is available on the user interface builder's palette. It allows the user to place a view holder widget onto the canvas being designed. Such a holder can take advantage of some of the widget properties defined by the user interface builder such as sliders etc. However, the developer must supply the majority of the code that connects the graphic contents of the view holder to the application as well as the code which actually generates the graphics.

### 29.2.2 How do you create a custom view?

<figure><img src="image_138.png" /><figcaption>Figure 29.3: Defining a custom view</figcaption></figure>

To create a custom view a user must first place a view holder onto the canvas representing the window being constructed. For example, in Figure 29.3, we have placed a view holder across the majority of the window and added a horizontal and vertical slider. This view is then linked to the window via an instance variable specified in the view's properties window.

The result of this is that when the user interface window building software encounters this window's definition (held in a class side window specification method) it will construct a window with four buttons and a scrollable view. However that is all that it will do. It will not attempt to perform any operations to determine what the interior of the view should look like.

### 29.2.3 Managing a custom view

Associated with this view holder will be a model, a controller and a view instance. As you will note from these classes custom views are implemented and controlled using the traditional MVC framework described earlier in this part of the book. Remember:
* Views control what is displayed on the screen.

* Controllers handle user interaction.

* Models hold the domain data to be displayed by the view.

Therefore it is in the view class that the developer must define a method which will specify what the custom view widget will display. This method is the `displayOn:` method. It takes one parameter which is a `GraphicsContext`. GraphicsContexts are objects which work with windows to display graphical objects (determining how the graphic object should be rendered).

The `displayOn:` method is sent by the system to the view whenever a change has occurred in one of the objects on which it depends (such as the model) or when the screen needs to be updated (for example, after a window which has been partially covering the view is closed).

For the view to determine what it should display it needs to communicate with the model which holds the data. It must therefore have a link to the model (whether it is a separate object or the instance of application model which holds the parent window).

Finally, the view must also work with a controller. This controller will determine what action the application should take whenever the user interacts with the view widget. Note that this controller does not attempt to control how the user interacts with the whole window, rather it is only concerned with the user's interaction with the view. For example, what happens when the user clicks in the view etc.

We shall now consider how the SmallDraw application is structured.

## 29.3 The structure of the application

Figure 29.4 illustrates the inheritance structure between the classes used in the SmallDraw application. This class hierarchy is typical of an application which incorporates a custom view. For example, we have an `ApplicationModel` hierarchy with the main SmallDraw application. We have a `Controller` subclass (`DrawingController`), a `Model` subclass (`DrawingModel`) and a `View` subclass (`DrawingView`). In addition we have three types of object which can be drawn in a SmallDraw drawing: `BoxWidget`, `CircleWidget` and `PointWidget`. The only difference between these three classes is what is drawn on to the graphics context representing the view. The `DrawingWidget` class from which they all inherit defines common attributes used by all objects displayed within a `DrawingView` (such as their origin, the extent of their boundary and the size of their border). Each of these classes will be considered in more detail in a later section in this chapter.

<figure><img src="image_139.png" /><figcaption>Figure 29.4: Inheritance in SmallDraw</figcaption></figure>

Note that the dashed line between the `Object` class and the `View` class indicates that there are a number of classes between these two in the actual class hierarchy. It is useful to examine these classes yourself to see what facilities they add.
<figure><img src="image_140.png" /><figcaption>Figure 29.5: The object relationships</figcaption></figure>

However, what inherits from what is only part of the story for any object oriented application. Figure 29.5 illustrates the next part of the story: how the objects relate to one another within a working application (note this diagram only presents the user defined objects within the application. There are other objects such as the `UIBuilder` which are also involved but which are generated by VisualWorks).

As you can see from Figure 29.5 the `SmallDraw` application model has instance variables which possess links to the `drawingModel` and the `drawingView`. The presence of a link to the `drawingView` object allows the window building facilities associated with the SmallDraw window to inform the view that it needs to redisplay itself. The link to the `drawingModel` allows the effects of user interaction outside the view to be passed onto it. For example, the user selects which object to add to the drawing by selecting one of three buttons at the top of the SmallDraw window (Figure 29.1). The user's choice must be passed through to the `drawingModel` so that it can add the appropriate drawing object to its list of displayed objects.

It is also worth noting that if you examine the `DrawingModel`, `DrawingView` and `DrawingController` you will see that these three classes exhibit the classic MVC structure. The `View` and the `Controller` have knowledge of each other and the `Model`, whereas the `Model` knows nothing about the `View` or the `Controller`. This is because VisualWorks records the `View` as a dependent of the `Model` when the view records the presence of the model (using the `super model: aModel` message expression).

Finally it is worth pointing out that in this case the `DrawingModel` is a relatively simple model which merely records a set of nodes in an `OrderedCollection`. These nodes could be anything and could be displayed in any way. It is the nodes themselves which determine what they should look like when drawn.

## 29.4 The interactions between objects

We have now examined what the physical structure of the application is but not how the objects within that application interact. In many situations this can be extracted from the source code of the application (with varying degree's of difficulty). However, in the case of a custom view within an `ApplicationModel`, it is useful to explicitly describe the system interaction. There are four different interactions in the system and each will be considered separately.

We shall adopt the following conventions for the diagrams illustrating the interactions between the objects (these diagrams are based on the mechanism diagrams described by [Rumbaugh et al 1991]):

* a solid arrow indicates a message send,

* a dashed arrow indicates instance creation,

* a square box indicates a class,

* a round box indicates an instance,

* a name in brackets indicates the type of instance,

* numbers are used to indicate the sequence of message sends.
### 29.4.1 Initialization

<figure><img src="image_141.png" /><figcaption>Figure 29.6: Object interaction during initialization</figcaption></figure>

When the `SmallDraw` application is opened (i.e. when the message `open` is sent to the `SmallDraw` class) an instance of `SmallDraw` is created and sent the message `initialize` (as illustrated in Figure 29.6). This results in the creation of two further instances one a `drawingView` and the other a `drawingModel`. The `drawingController` is automatically instantiated when the view is displayed (note the type of controller to be used is specified by the `drawingView` in the instance variable `defaultController`).

Once the two instances have been created the message `model:` is sent to the `drawingView`. This in turn causes the `drawingView` to become one of the drawing models dependents. Note that this last message send is defined in the `DependentPart` class, which is one of the superclasses of `DrawingView`.

At this point the structure required by the custom view is in place. It is now possible for the application model `SmallDraw` and the user to interact with the `drawingView` and `drawingController`.

### 29.4.2 Changing the type of graphic object to be displayed

<figure><img src="image_142.png" /><figcaption>Figure 29.7: Changing the graphic object to be added</figcaption></figure>

As we have used the user interface builder to add buttons to the main window which will be used to determine which type of graphic object to add to the drawing, we require some way of passing that information onto the objects involved in managing and maintaining the custom view. That means we must inform the model of the type of object which will be added.

The actual interaction illustrated in Figure 29.7 involves the message `setBoxStyle` being sent to the `SmallDraw` application when the **Box** style button is selected in the main window. This message is sent in response to an event being raised (we do not cover how this works in this book: it is left as an exercise for the reader).

When the message `setBoxStyle` is received by the `smallDraw` object, a further message is then sent to the `drawingModel` (which `smallDraw` has a link via the instance variable `drawingModel`) setting the current style to the symbol `#box`. The style value can currently be one of `#box`, `#circle` or `#point`.

### 29.4.3 Adding a new graphic object

<figure><img src="image_143.png" /><figcaption>Figure 29.8: Adding a box graphic object</figcaption></figure>
The action of adding a new graphic object to the drawing displayed by the custom view in the SmallDraw application is initiated by the user pressing the left mouse button. Historically the mouse buttons were known as red, yellow and blue for the left, middle and right mouse buttons. This was because the original system on which Smalltalk was developed had multi-color mouse buttons (colored red, yellow and blue). Although Smalltalk is now available on systems with one, two and three mouse buttons (all of which tend to be shades of the same color e.g. white, gray or cream) there are still places in the system where reference is made to the color of the mouse button - this is one of them.

When the left mouse button is pressed a `redButtonActivity` message is sent to the `drawingController` (as illustrated in Figure 29.8). This allows the `drawingController` to decide what action to perform in response to the left mouse button being pressed. For example, an application may specify that a menu should be displayed or that any object under the mouse is selected etc. In the case of the SmallDraw application the action is to place a graphic object (of the appropriate style) at the current cursor location. To do this, the `drawingController` sends an `addWidgetAt:` message to the `drawingModel`.

Next the `drawingModel` creates a new instance of the appropriate type of object. In the diagram illustrated in Figure 29.8 the current style is that of `#box`. Therefore a new instance of `BoxWidget` is created. This `boxWidget` instance is then sent a message `origin:` which sets its position within the view. The `boxWidget` is then added to the `orderedCollection` used to hold all the graphic objects. Next the `drawingModel` sends itself the `changed:with:` message so that all of its dependents can be informed that a change has taken place.

This results in an `update:with:` message being sent to the `drawingView` via the dependency mechanism. The `drawingView` then sends a `displayOn:` message to the objects to be displayed. The `boxWidget` then uses a border object to display itself on the `graphicsContext`.

This section has outlined the most difficult part of constructing a custom view for the novice - working out what is sent where, by what and when. The thing to remember is that you are slotting your application specific code into a generic framework. However at this stage it is often much easier to look at what someone else has done and to use it as the basis of what you require. While this approach can be extremely useful as a learning exercise it is still important to become familiar with this framework. One way to do this is to place `self halt` messages into strategic methods (such as `update:with:` and `displayOn:` in the `drawingView` object) and then to use the debugger to explore the objects and messages which have been sent.

### 29.4.4 Refreshing

The final set of interactions which you should be aware of relate to refreshing the window following some operation which invalidates part or all of the screen display (such as the movement of a partially overlapping window). In such circumstances the message `checkForEvents` is sent to the `applicationWindow`, the application controller (which acts as the controller for the overall application). (Note that in Figure 29.9 the large dashed line indicates missing message sends).

The `applicationWindow` then sends a `displayDamageEvent:` `aRectangle` message to itself. This message basically means that an event is raised which indicates that there may be some damage to the displayed area (specified by a rectangle). If the `applicationWindow` is open, then the message `displayOn:` will be sent to the `drawingView`.

The `displayOn:` method in `drawingView` (as opposed to that defined in the "wi dget" classes) obtains a collection of objects to be displayed from the `drawingModel` using the `nodes` message and sends each object a `displayOn:` message as part of a `do:` message expression. This results in each of the graphic objects being redraw on the screen.

<figure><img src="image_144.png" /><figcaption>Figure 29.9: Refreshing a custom view</figcaption></figure>
## 29.5 The classes involved

This section describes how to implement the classes in the SmallDraw application in detail (see Figure 29.4 which illustrates the classes in this application). We will first consider the SmallDraw application itself before considering the three classes involved in the MVC framework ( DrawingModel, DrawingView and DrawingController) and will conclude by describing the “widget” classes: DrawingWidget, PointWidget, CircleWidget and PointWidget.

### 29.5.1 The SmallDraw class

The SmallDraw class is a subclass of ApplicationModel. It possesses two instance variables, drawingView (which is actually an aspekt referencing the custom view) and drawingModel. The class definition is presented below and can be typed in using the System Browser. Note that this assumes that the class is being defined in a class category called SmallDraw.

```kotlin
ApplicationModel subclass: #SmallDraw
    instanceVariableNames: 'drawingView drawingModel '
    classVariableNames: ''
    poolDictionaries: ''
    category: 'SmallDraw'!
```

The SmallDraw application provides the main window for the application. It possesses four buttons, and a view as illustrated in Figure 29.10. You should use the canvas tool and the palette to create a window which resembles this. Next use the properties tool to define the properties for the four buttons and the view. The figure illustrates the actions defined for each button and the aspect name of the custom view.

<figure><img src="image_145.png" /><figcaption>Figure 29.10: Defining the graphic elements of the SmallDraw application</figcaption></figure>

Next use the definer tool to define the canvas tools Launcher to create stub methods for the actions illustrated in Figure 29.10.

We shall now define the initialize method in the initialize protocol in the SmallDraw class (use a browser to do this). The initialize method creates an instance of the DrawingView class, the DrawingModel class and links them together. The method is presented below:

```kotlin
initialize
    drawingView := DrawingView new.
    drawingModel := DrawingModel new.
    drawingView model: drawingModel.
```

You are now ready to define each of the action methods in the actions protocol. The first method we shall consider is the exit method which is executed when the exit button is selected. This message uses the closeRequest method we saw in the last chapter to terminate the application:

```kotlin
exit
    self.closeRequest
```
The next method we shall consider is the `setBoxStyle` method. This method is executed when the **Box** button is selected. This method sends the `style:` message to the `drawingModel` with the parameter `#box`. That is, it causes the current graphic object style to be set to `#box`.

```
setBoxStyle
    drawingModel style: #box.
```

In addition there are two other methods which set the style of object to be added. These are `setCircleStyle` and `setPointStyle`. They are exactly the same as the `setBoxStyle` method except that they pass the symbols `#circle` and `#point` to the `drawingModel` via the message `style:`. The `setCircleStyle` method is called whenever the **Circle** button is selected and the `setPointStyle` method whenever the **Point** button is selected:

```
setCircleStyle
    drawingModel style: #circle.
```

```
setPointStyle
    drawingModel style: #point.
```

Finally the `aspects` protocol (automatically generated for you if you have used the definer) will contain a single method called `drawingView`. This is an accessor method for the aspect `drawingView`:

```
drawingView
    ^drawingView
```

As usual the SmallDraw application is instantiated by sending the message `open` to the class `SmallDraw`. For example:

```
SmallDraw open
```

## 29.5.2 The DrawingModel class

The `DrawingModel` class is a subclass of `Model`. It possesses two instance variables `nodes` and `style`. The instance variable `style` indicates the type of object to add to the collection of objects in `nodes`. The class definition is:

```
Model subclass: #DrawingModel
    instanceVariableNames: 'nodes style '
    classVariableNames: ''
    poolDictionaries: ''
    category: 'SmallDraw'
```

The `DrawingModel` class comment is left as an exercise for the reader.

Having defined the `DrawingModel` class and class comment we are now ready to define the `initialize` method. As usual we will place this method in an `initialize` method protocol. The `initialize` method initializes the two instance variables `nodes` and `style`. A new ordered collection is instantiated for the first and the `style:` accessor method is used to set the second (with a default style of `#box`):

```
initialize
    nodes := OrderedCollection new.
    self style: #box.
```

We are now ready to define the *accessing* methods for `DrawingModel`. These methods (defined within an *accessing* protocol) access the instance variables of the class. For example, `nodes` and `style` retrieve the value of their associated instance variables, while `style:` resets the instance variable `style`.

```
nodes
    ^nodes.
```

```
style
    ^style
```

```
style: aSymbol
```
```
style ::= aSymbol
```

Next we define an *updating* protocol. This protocol will hold a single method `addWidgetAt:`. This method adds the appropriate type of graphic object to the objects held in `nodes`. The instance variable `style` is used to determine the type of object to add. The parameter `aPoint` indicates the location, within the drawing view, at which the object should be displayed. Finally, the method informs the `drawingModel` that something has changed and that its dependents may be interested in that change.

```kotlin
addWidgetAt: aPoint

| aNode pos |
self style = #point ifTrue: [aNode := PointWidget new].
self style = #box ifTrue: [aNode := BoxWidget new].
self style = #circle ifTrue: [aNode := CircleWidget new].
aPoint = nil ifTrue: [pos := 0 @ 0] ifFalse: [pos := aPoint].
self nodes add: (aNode origin: pos).
self changed: #object with: aNode.
```

We will also define a single class side method `new`. This method will extend the functionality of the new method by sending the message `initialize` to a newly created instance. The method is defined in the class side protocol *instance creation*:

```kotlin
new
    ^super new initialize.
```

### 29.5.3 The DrawingView class

The `DrawingView` class is a subclass of the `View` class. It possesses a single instance variable called `defaultControllerClass`. The contents of this variable will be used to instantiate the correct type of controller (in this case an instance of `DrawingController`).

```kotlin
View subclass: #DrawingView
    instanceVariableNames: 'defaultControllerClass '
    classVariableNames: ''
    poolDictionaries: ''
    category: 'SmallDraw'
```

The class comment for the `DrawingView` class is left as an exercise for the reader. The `initialize` method for the `DrawingView` class is defined as:

```kotlin
initialize
    super initialize.
    defaultControllerClass := DrawingController.
```

This method is defined within the `initialize` protocol. To ensure that all initialization done in superclasses is also carried out in this class, the method first sends the message `super initialize`. It then initializes the `defaultControllerClass` instance variable.

Following the conventions laid down in the system view class hierarchy we will define a `defaultControllerClass` accessor method in a protocol referred to as *controller accessing*. This method returns the contents of the `defaultControllerClass` instance variable:

```kotlin
defaultControllerClass
    ^defaultControllerClass
```

In the *model accessing* protocol we will define an `updater` method for the model associated with the `drawingView` instance called `model`:

```kotlin
model: aModel
    super model: aModel.
    self invalidate.
```

This method uses an inherited version of the `model`: method to set the model and then sends the message `invalidate` to itself. This informs the view that some part of what is currently being displayed may need to be redrawn. This will cause a `displayOn: aGraphicsContext` message to be sent to self.
In the *updating* protocol we need to define a method which will catch the result of the change message set when a new widget is added to the model. This is the `update:with: message`. In our case we merely wish to draw the newly added object in the view:

```ruby
update: anAspect with: anObject
anAspect == #object ifTrue: [anObject displayOn: self graphicsContext].
```

We now need to define the `displayOn:` method for the drawing object within a *displaying* protocol. This is sent to the drawing view when what is being displayed needs updating (e.g. when part of the window is uncovered). This method sends the `displayOn:` message to all the elements currently held in the nodes list of the `drawingModel`:

```ruby
displayOn: aGraphicsContext
    self model nodes do: [:node | node displayOn: aGraphicsContext]
```

Finally we need to extend the class side method in the *instance creation* protocol so that it sends the message `initialize` to the newly created instance:

```ruby
new
    ^super new initialize
```

### 29.5.4 The DrawingController class

The `DrawingController` class is a subclass of the `ControllerWithMenu` class. This is because we wish to catch the left mouse button pressed event. This is simplified for the `ControllerWithMenu` class as a method called `redButtonActivity` is called whenever the left mouse button is pressed.

```ruby
ControllerWithMenu subclass: #DrawingController
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'SmallDraw'
```

The class comment for the `DrawingController` is left as an exercise for the reader. Only two methods are defined for this class: `controlLoop` and `redButtonActivity`. Both methods are defined in the *control defaults* protocol. The `controlLoop` method is called whenever the cursor enters the area of the window displayed by the `DrawingView`. This `controlLoop` method merely changes the type of cursor displayed (to that of a cross) when the user moves the cursor onto the drawing area. It then sends the message `super controlLoop`. This allows the control operations defined higher up the class hierarchy to be invoked:

```ruby
controlLoop
    "Change the cursor to a cross-hair for drawing."
    Cursor crossHair showWhile: [super controlLoop].
```

Finally the `redButtonActivity` method defines what should happen when the left mouse button is pressed. In this case a new graphic object is added to the drawing at the point indicated by the current cursor position:

```ruby
redButtonActivity
    "Place widget at the current cursor position when left button pressed"
    self model addWidgetAt: self sensor cursorPoint.
```

### 29.5.5 The DrawingWidget class

The `DrawingWidget` class is an abstract superclass which captures all the elements which are common to graphic objects which will be displayed within a drawing. The `DrawingWidget` class (a subclass of `Object`) defines three instance variables `origin` (the cursor position when the mouse is clicked), the `extent` (or size of the object) and the `border`:

```ruby
Object subclass: #DrawingWidget
    instanceVariableNames: 'origin extent border '
```
classVariableNames: ''
poolDictionaries: ''
category: 'SmallDraw'

The `initialize` method for this class (defined in the `initialize` protocol) sets the default values for each of the instance variables. For example:

initialize
    origin := 0 @ 0.
    extent := 30 @ 30.
    border := Border width: 1.

You can experiment with these values by changing the `extent` or the `border` (do so and see what the effects are).

Next we will define the methods in the *accessing* protocol. These methods retrieve and set the border, the `origin` and the `extent`:

border
    ^border

border: aBorder
    border := border.

origin
    ^origin

origin: aPoint
    origin := aPoint.

extent
    ^extent

extent: aPoint
    extent := aPoint

The *displaying* protocol has two methods in it: `displayOn:` and `bounds`. The `displayOn:` method is a subclass responsibility. This is because each subclass needs to specify what it should look like independently. This is done in the `displayOn:` method.

displayOn: aGraphicsContext
    self subclassResponsibility

The `bounds` method calculates the bounds of the object using the `origin` and the `extent`. The return object is an instance of `rectangle`.

bounds
    ^origin extent: extent.

Finally, as before we need to extend the basic instance creation method `new` by sending the message `initialize` to the newly created instance. This is left as an exercise for the reader.

### 29.5.6 The PointWidget class

The `PointWidget` is a subclass of `DrawingWidget` that specifies how a point should be drawn in a drawing. It defines a single instance variable `diameter`. This indicates the size of the point to draw:

DrawingWidget subclass: #PointWidget
    instanceVariableNames: 'diameter '
    classVariableNames: ''
poolDictionaries: ''
category: 'SmallDraw'

The `initialize` method specifies the default size of the `diameter`. As the `DrawingWidget` defines some initializations as well, we must send the message `super initialize`.

initialize
    super initialize.
diameter := 4.
The displaying protocol contains the class specific `displayOn:` method. This method uses the `displayDotOfDiameter:at:` message to draw a point on the graphics context:

```
displayOn: aGraphicsContext
aGraphicsContext displayDotOfDiameter: diameter at: origin
```

### 29.5.7 The CircleWidget class

The `CircleWidget` is another subclass of `DrawingWidget`, however it only redefines the `displayOn:` method such that it draws a circle within the bounds returned by the `self bounds` message:

```
displayOn: aGraphicsContext
| bnds |
"Get the bnds of the node."
bnds := self bounds.
"Draw the circle representing the object on screen"
aGraphicsContext displayArcBoundedBy: bnds
startAngle: 1 sweepAngle: 360.
```

### 29.5.8 The BoxWidget class

The `BoxWidget` class is the last subclass of `DrawingWidget`. Again it only redefines the `displayOn:` method. This time the border itself is displayed.

```
displayOn: aGraphicsContext
| bnds rect |
"Get the bnds of the node."
bnds := self bounds.
"Display the nodes border."
rect := self border insetDisplayBoxFor: bnds.
self border displayOn: aGraphicsContext forDisplayBox: rect.
```

## 29.6 Add a delete widget option

The exercise associated with this chapter is to extend the SmallDraw application by adding a delete option. This could be done by adding a fifth button to the window labeled delete. This would then set the style to `#delete`. The `redButtonActivity` method would then need to be changed to send either an `addWidgetAt:` message or a `deleteWidgetAt:` message. It would then be the responsibility of the `drawingModel` to find and remove the appropriate graphic object, remembering of course to send the changed message to itself.

## 29.7 Summary

This chapter has introduced the concept of custom views and how they are implemented. The use of custom views provides a great deal of flexibility for developers when constructing graphic user interfaces. In addition the availability of the user interface builder simplifies the task of creating such interfaces and allows the developer to concentrate on the implementation and control of the view rather than issues such as scrolling, or event capture.

## 29.8 Further reading

One of the best places to look for further guidance on this area is in the VisualWorks Cookbook and Tutorial which accompanies the VisualWorks system. In addition almost any book which discusses the MVC will be a useful reference.
Part Six

# Further Smalltalk
# 30. Memory Management and Garbage Collection

## 30.1 Introduction

This chapter describes how Smalltalk manages its memory and how automatic garbage collection is achieved. Automatic garbage collection and memory management are one of the main features lacking from some other object oriented languages (such as C++). We therefore begin the chapter by considering why high level object oriented languages should provide automatic memory management and garbage collection. A discussion is then presented of the way in which VisualWorks manages its memory and identifies those objects whose memory can be collected and reused. The process, by which objects can be relocated into permanent memory, is described. This can improve the efficiency of the garbage collector. Following this we consider the exception handling facilities in Smalltalk.

## 30.2 Why have automatic memory management?

One of the many advantages of Smalltalk over languages such as C++ is that Smalltalk automatically manages memory allocation and reuse. It is not uncommon to hear C++ programmers complaining of the problems they have had spending many hours attempting to track down a particularly awkward bug only to find it was a problem associated with memory allocation or pointer manipulation. Similarly, an often heard problem from C++ developers is that of memory creep - a problem which occurs when memory is allocated at some point but never freed up. The application then either eats up all available memory or runs out of space thus producing a run-time error.

Most of the problems associated with memory allocation in languages such as C++ are because the programmer must not only concentrate on the (often complex) application logic but also on memory management. They must ensure that they allocate only that memory which is required and deallocate it when it is no longer required. This may sound simple, but it is no mean feat in a large complex application.

An interesting question to ask is "why do programmers have to manage memory allocation?". This is a reasonable question to ask. For example, there are few programmers today who would expect to have to manage the registers being used by their programs, however 20 or 30 years ago the situation was very different. One answer to the memory management question, often cited by those who like to manage their own memory, is that "it is more efficient, you have more control, it is faster and leads to more compact code". Of course, if you wish to take these comments to their extreme, then we should all be programming in assembler. This would enable us all to produce faster, more efficient and more compact code than that produced by Pascal, C++ or Smalltalk.

The point about high level languages, however, is that they are more productive, introduce fewer errors, are more expressive and are efficient enough (given modern computers and compiler technology). The memory management issue is somewhat similar. If the system automatically handles the allocation and deallocation of memory, then the programmer can concentrate on the application logic. This makes them more productive, removes problems due to poor memory management and when implemented efficiently, can still provide acceptable performance.
## 30.3 VisualWorks memory management

<figure><img src="image_146.png" /><figcaption>Figure 30.1: Memory organization in VisualWorks</figcaption></figure>

VisualWorks provides automatic memory management. Essentially it does so by allocating a portion of memory as and when required. Then, when memory is short it searches through memory looking for areas which are no longer referenced. These areas of memory are then freed up (deallocated) so that they can be re-allocated. This process is often referred to as “garbage collection”. A second process, invoked with garbage collection is memory compaction. This involves moving all the allocated memory blocks together so that free memory is contiguous rather than fragmented. The Smalltalk memory is divided up as shown in Figure 30.1.

As can be seen from this figure there is an area of memory allocated to the Virtual Machine (the object engine). This area, below the black line, holds both the virtual machine and the memory it uses. This area is outside the scope of this book and will therefore not be considered in greater detail. The regions in the Object Memory are used to hold the objects created by the system and by user programs. It is useful to distinguish between parts of this memory, not least because the VisualLauncher offers the user two different types of garbage collection, one called “Garbage Collection” and one called “Global Garbage Collection”. The options relate to which parts of memory are processed.

### 30.3.1 NewSpace and OldSpace

NewSpace is fixed in size (the default for NewSpace is about 200 K) and is used to hold newly created objects. When the amount of memory used in NewSpace crosses the scavenge threshold, the “generation scavenger” is called. This is a program which frees up memory from objects which are no longer referenced. This memory can then be used again. If an object has survived for long enough it may get moved in OldSpace.

References to objects in OldSpace are not quite as fast as those to objects in NewSpace, however, OldSpace is not fixed in size and can grow as long as there is memory available. The scavenger does not operate in OldSpace as it is optimized for NewSpace handling objects which are rapidly created and then de-referenced.

### 30.3.2 LargeSpace

This is a special area of memory for very large byte objects (typically larger than 1 KB) e.g. bitmaps. This saves the need to move large areas of memory around because of small frequently used areas of memory being repeatedly allocated and deallocated. Objects in LargeSpace are only freed up or moved when LargeSpace is compacted as part of a “compacting garbage collection” or when LargeSpace has filled up.
### 30.3.3 PermSpace

This is used to house objects which are rarely eligible for garbage collection. Examples of such objects are the system classes, tools and compilers. None of the garbage collections attempt to process this area of memory except the "Global garbage collector". This is initiated by the user from the VisualLauncher. Again this is a performance "tweak" and means that most of the time items such as a class do not have to be checked to see if the memory they occupy should be reclaimed nor must PermSpace be compacted.

## 30.4 Garbage collection and memory compaction

There are a number of different ways in which garbage collection and memory compaction can occur. The first is the "Generation Scavenger". This is called whenever NewSpace exceeds the *scavenge threshold*. It only processes objects in NewSpace (although it does place objects in OldSpace).

Another garbage collector is the *incremental garbage collector* (or IGC). This is called from Smalltalk code (as opposed to the scavenger which is called automatically by the Virtual Machine). The IGC reclaims objects in OldSpace, NewSpace and LargeSpace. It is called the *incremental garbage collector* because it works in an incremental manner to avoid disturbing the executing VisualWorks environment.

The two remaining garbage collectors are the "Compacting Garbage Collector" and the "Global Garbage Collector". These two garbage collectors are under user control and are initiated from the VisualLauncher. The compacting garbage collector is run when the user selects the "Garbage Collection" option on the special menu on the Launcher. The global garbage collector is run when the user selects the "Global Garbage Collection" option on the same menu (and processes all of the memory available).

Finally, there is a data compactor which runs on the OldSpace which does not do any garbage collection, only memory compaction. This runs considerably faster than the garbage collectors.

## 30.5 Placing objects in PermSpace

PermSpace is an error of memory which is intended to hold objects which will never die or which will only rarely die. This means that most of the garbage collection methods do not need to worry about what is in PermSpace, thus reducing the amount of memory they must scan. Obviously some of the objects in PermSpace may die off, the global garbage collector therefore scans PermSpace as well.

It is possible to move objects from OldSpace to PermSpace to increase the performance of the garbage collector. This effect is achieved because by moving objects out of OldSpace the number of objects which must be considered is reduced. This can have a major effect on the performance of the garbage collector.

When you start up your "clean" image, most of the objects (including classes) present in the system will be located in PermSpace. When you create new objects these will reside in NewSpace or OldSpace. To relocate them into PermSpace it is necessary to save the current image using the "**Perm Save As ...**" option from the "**File**" menu option in the VisualLauncher. This writes the objects in OldSpace into PermSpace in the saved image. It does not affect where objects are located in the current (executing) image, only in the saved image. It is therefore necessary to exit the image and start up the newly saved image to have an executing image, in which the objects are stored in PermSpace.

There will however be a number of objects in PermSpace which are transient (i.e. likely to die in the short term). These objects will have been placed into PermSpace, because all objects, whether or not you wanted them to, will have been saved into PermSpace. Example of such objects may include windows, objects with which you were working etc. To remove these from the image (thus improving the performance of the garbage collector) perform a global garbage collection. Once you have done this save the image in the normal manner (i.e. "**Save as...**"). Having started up the newly saved image you could increase the time taken to start the image by performing one last save of the image. This is necessary because the global garbage collector compacts the objects in PermSpace. This means that when the image is started up, the system must relocate these objects. If you make one more image, then the objects will already have been relocated and the startup time will be minimized.
It is also possible to move objects from PermSpace into OldSpace. This can be done using the
“**Perm Undo As...**” option again from the “**File**” menu option in the VisualLauncher. This will move
**all** objects from PermSpace into OldSpace. This will obviously have an impact on the performance of
the garbage collector, and is not recommended unless you intend to remove a large number of objects
which were previously in PermSpace. You should then save the image again using the “**Perm Save
As...**” option.
# 31. Concurrency in Smalltalk

## 31.1 Introduction

This chapter presents and explains a short example of how concurrency can be accomplished with Smalltalk. It also considers lazy evaluations (i.e. you only perform the evaluation if you absolutely have to), futures (you start an evaluation now which you will need later) and persistence.

The remainder of the document is structured in the following manner: Section two introduces the concept of concurrency, Section three briefly discusses processes within Smalltalk. Section four introduces the concepts used in the time slicing scheduler and Section five explains how future and lazy evaluators may be implemented in Smalltalk.

## 31.2 Concurrent processes

The concepts behind object oriented programming lend themselves particularly well to the concepts associated with concurrency. For example, a system can be described as a set of discrete objects communicating with one another when necessary. In most Smalltalk implementations, only one object may be executing at any one moment in time. However, conceptually at least, there is no reason why this restriction should be enforced. For example, the basic concepts behind object orientation still hold, even if each object executes within a separate independent process.

Traditionally, a message send is treated just like a procedural call, in which the calling object's execution is blocked until a response is returned. However, we could extend this model quite simply to view each object as a concurrently executable program module, with activity starting when the object is created and continuing even when a message is sent to another object (unless the response is required for further processing). In this model, there may be very many (concurrent) objects all executing at the same time. Of course this introduces issues associated with resource allocation etc. but no more so than in any concurrent system.

One implication of this concurrent object model is that objects are necessarily larger than in the traditional single execution thread approach. This is because the overhead of having each object as a process. A process scheduler for handling these processes and resource allocation mechanisms mean that it is not feasible to have integers or characters etc. as separate processes. (Note in Smalltalk integers etc. are objects. In such a system there might be a separate type of object which is a concurrent object which is assumed to be a large grained object).

Smalltalk has limited built-in support for concurrency. However, it does support Processes and Semaphores as primitive types. Other conventional inter-process communication and protection mechanisms such as SharedQueues and critical regions, are implemented in terms of these primitives. However, the processor scheduler (part of the virtual machine) implements a naive non-preemptive scheduling policy, with limited support for re-scheduling within a particular priority level. Further, once a high-priority process is running, no lower priority process will run until the high priority process suspends or terminates. For these reasons, the basic Smalltalk system contains only a few processes and typical applications using concurrency do not create more than a few tens of processes.

However, as the source code is available to the developer it is possible to extend the scheduler such that a pre-emptive policy is introduced. This is described in Section 3 following on from a discussion of the facilities provided in Smalltalk which enable the construction of such a scheduler.
## 31.3 Processes in Smalltalk

For further details on processes in Smalltalk see the appropriate system documentation, for example in VisualWorks see Chapter 8 in the Smalltalk User's Guide, Release 4.1 and pages 25-40 of [Lalonde and Pugh 1991b]. In this section we shall only provide a brief introduction to this subject.

A Smalltalk process is a non-preemptive light-weight process. That is, a Smalltalk process will run to completion unless a higher priority process attempts to gain control Smalltalk does not attempt to share the processor time amongst processes of the same priority. When the highest priority is held by multiple processes, the active process can be bumped to the back of the line with the expression: `Processyield` - otherwise it will run until it is suspended or terminated before giving up the processor. A process that has been bumped will regain control before a process of lower priority.

This of course implies that every process has an associated priority. By default a process inherits the same priority as the process which spawned it. The *priority* of a process can be changed using the *priority: message*.

The process which is currently being executed by the processor is termed the active process. A process can also be waiting to use the processor or stopped, waiting for some resource. There are a number of message related to the state of a process these are:

* `aProcess resume`. This schedules a process.

* `aProcess suspend`. This stops the process from executing.

* `aProcess terminate`. This unschedules the process permanently.

There are a number of messages which are sent directly to the process scheduler which can be useful in working with active processes. These are:

* `Processor activeProcess`. This returns the process which is currently executing.

* `Processor activePriority`. This returns the priority of the active process; i.e. the priority of the process which is currently executing.

* `Processor terminateActivity`. Permanently removes the active process from execution.

Note that the messages are sent to a global variable `Processor`, which holds the instance of `ProcessorScheduler`.

For a process to be spawned from the current process there must be some way of creating a new process. This is done using one of four messages to a block. These messages are:

<table><tr><td>aBlock fork</td><td>This creates and schedules a process which will execute the block. The priority of this process is inherited from the parent process.</td></tr><tr><td>aBlock forkAt: aPriority</td><td>This creates and schedules a process executing the block at a specific priority.</td></tr><tr><td>aBlock newProcess</td><td>This creates a new process. It does not schedule the process. The process is created with the same priority as the parent block. It can be scheduled using the resume message.</td></tr><tr><td>aBlock newProcessWith: anArrayOfParameters</td><td>This message creates a new process with the same priority as the parent process. An array of parameters is passed to the block.</td></tr></table>

### 31.3.1 Semaphores

Semaphores provide a (simple) means of synchronization between multiple processes. For example, if two processes are executing and one must not pass a certain point until the other has completed some operation, then a semaphore between the two processes can be used as a flag to indicate to the first process that the operation has been completed.
The Semaphore class provides facilities for achieving simple synchronization, it is simple because it only allows for two forms of communication `signal` and `wait`. Essentially, a signal puts a 1 in the queue representing the semaphore and wait pops a 1 off the semaphore. The advantage of this approach is simplicity and efficiency. The disadvantage of this approach is that more complex synchronization is not possible. Of course, more complex synchronization can be achieved using semaphores and shared queues, but the key thing is that it is not directly supported.

When a process sends a wait message to a semaphore, that process will only be allowed to proceed if a corresponding signal has been sent to the semaphore. If there is no corresponding signal, then the process will be suspended. It will only be resumed when such a signal is sent.

Semaphores are ordered queues. If five waits have been sent to a semaphore then the fifth wait will only be serviced once five signals have been sent to the same semaphore. This means that they pay no attention to the priority of the process ( unlike the scheduler). A high -priority process must wait in line for a signal in just the same way as a low priority process.

There are two instance creation methods for the `Semaphore` class. These are:

<table><tr><td>Semaphore new.</td><td>This creates a new empty semaphore.</td></tr><tr><td>Semaphore forMutalExclusion.</td><td>This creates a new semaphore with a single signal in it. This is a special type of semaphore which is used in association with a special message <em>critical</em> and provides for mutual exclusion.</td></tr></table>

As stated above there are two synchronization messages; `signal` and `wait`:

<table><tr><td>aSemaphore signal.</td><td>This increments the semaphore <em>signal</em> count.</td></tr><tr><td>aSemaphore wait.</td><td>This increments the semaphore <em>wait</em> count and causes the sender to suspend if fewer signals were previously sent.</td></tr></table>

An additional message to a semaphore is `critical`. This should only be sent to a semaphore which was created using the `forMutalExclusion` instance creation message. The format of this message expression is:

`aSemaphore critical: aBlock`

This is useful if the block is accessing shared information. This message only allows the block to execute if no other block controlled by the same semaphore is executing; otherwise, it causes the active process to suspend until the block can be executed. In effect it is performing the following process:

* Send a wait message to the semaphore.

* Executes the block.

* Send a signal message to the semaphore.

### 31.3.2 Shared queues

When distinct processes access shared objects, then the access to those objects must be carefully controlled. For example, if two objects were to access a common set of data and one was in the process of adding some data, then when another (higher priority) process pre-empts it and attempts to perform a different addition operation, the original changes might well be lost. Since the original addition was not completed the set could be in a partially modified state, this could have extremely unpredictable results.

Smalltalk does not provide protected collection classes (although again these could be implemented using semaphores etc.). Instead, Smalltalk provides a `SharedQueue` class which guarantees that only one process will be able to access it at a time and that the expression being performed will execute to completion without being pre-empted. The design of a shared queue is essentially that presented in the *Purple Book* [Goldberg and Robson 1989], in Chapter 15 starting on page 258-265.

Elements can be placed in a shared queue using the `nextPut:` message, while elements can be read from a shared queue using the `next` message. If no elements are currently in the shared queue when a `next` message is sent, then the sending process is suspended until a `nextPut:` message is sent to the queue. If three successive `next` messages are sent to an empty shared queue by three separate
processes, all three processes will be suspended. When a subsequent `nextPut:` message is sent to the shared queue, the first process to have sent a `next` message will be resumed. An additional message available is the `peek` message. This returns the next item in the shared queue, however unlike the `next` message, it does not remove it from the queue. The instance creation methods for a shared queue are:

```
SharedQueue new.
SharedQueue new: anInitialSize.
```

Both these messages return a shared queue. The three messages used with shared queues are:

```
aSharedQueue next.
aSharedQueue nextPut:
aSharedQueue peek.
```

The following passage is taken from page 36 [Lalonde and Pugh 1991b].

> "In general, creating new shared classes is relatively easy. A specialization of the original class is created with two new instance variables to play the role of the two semaphores (one semaphore for co-ordinating user access and another for mutual exclusion while executing critical code). Then, all operations with side effects are revised using the following template. If a method being revised is called `aMethod`, the critical section code is simply a variant of "super aMethod."."

For example:

```
aMethod: anObject
    mutualExclusionSemaphore critical: [super aMethod: anObject].
    readingSynchronisationSemaphore signal.
```

or

```
aMethod
    | anElement |
    readingSynchronisationSemaphore wait.
    mutualExclusionSemaphore critical: [anElement := super aMethod].
    ^anElement.
```

## 31.4 A concurrent Smalltalk example

This section presents an example to show how time slicing could be done within Smalltalk using the current process scheduler (based on an example produced by Hubert Baumeister - see end of section). The basic idea behind the effective control of multiple processes within Smalltalk is the introduction of a high priority process. This process wakes up every few milliseconds and regroups the processes in the waiting queue of the highest priority that has more than one process. It then goes back to "sleep" for a few milliseconds. It is thus time slicing between the various processes at the lower priority.

The approach taken in this section is that if it is necessary to develop a preemptive scheduler (that is one in which the processor time is shared between a given number of processes, rather than dedicated to a single process), then this can be done by using the facilities provided by the standard scheduler. In effect this results in two schedulers. One, is the system scheduler, the other is a user defined scheduler.

The system scheduler is still used to actually enable a process to execute. For example, it is still this scheduler which can suspend a process when a signal is sent to a semaphore.

The user defined scheduler is used to manage the queues of user processes waiting to be handed to the system scheduler. These queues are controlled by the user scheduler when ever it "wakes up". Of course, in order for it to gain control of the processor it MUST HAVE a HIGHER PRIORITY than all other user processes. It can then interrupt the user processes and select which process to initiate.

The key to the user defined scheduler is that it "wakes up" every few milliseconds. This can be simply and easily achieved using a `Delay`. This will send the process to sleep for the period of the delay. Actually, it will cause the process to suspend until the timer associated with the delay period sends the process a resume. It is this resume which will cause it to take control of the processor again.
Once the process wakes up it can determine which of the processes currently waiting to use the processor should be resumed next. One way in which this can be done is to regroup the processes in the waiting queue of the highest priority queue that has more than one process. Thus ensuring that a different process is at the head of the queue each time the user defined scheduler process “goes back to sleep”.

Check to see if time slicing is already being used.
If not set up the a new process to sleep for 5 milliseconds
and then to initiate the time slicing process.
Set the process to have the highest available priority.
Schedule the process for execution.

<caption>Figure 31.1: The time slicing algorithm</caption>

### 31.4.1 The source code for the example

As explained above the mechanism which allows this time slicing scheduler to work is the user of a `Delay`. This delay forces the user extensions to the scheduler to sleep. When it wakes up it selects a new process for execution using the `slice` method. It then goes back to sleep.

This continuous sleeping and slicing cycle can be achieved by spawning a new process (with the highest allowable priority). This process continually loops, sleeps and slices. The method which initiates this behaviour is `startTimeSlicing`. This method, defined in `time slice process` protocol, uses the algorithm in Figure 31.1. The actual Smalltalk method is presented below:

```ruby
startTimeSlicing
    "self timeStartSlicing"
    TimeSliceProcess notNil ifTrue: [^self].
    TimeSliceProcess :=
        [[true] whileTrue: [(Delay forMilliseconds: 5) wait.
            Processor slice]] newProcess.
    TimeSliceProcess priority: (Processor highestPriority).
    TimeSliceProcess resume.
```

Of course having set up such a process we must provide some way of killing the process. If this is not done, then this process will always run (until the image is deleted). This is in fact the reason why the new process was stored into a variable named `TimeSliceProcess`. This is of course a global variable and could easily have been stored as an instance variable of the `ProcessorScheduler` class. However, for ease of debugging it is often easier to store a process such as this in a global variable. This is because it is at a higher priority level then most user processes. If an unexpected "feature" has been introduced, the process can be killed by sending the message `terminate` to the contents of the `TimeSliceProcess` global variable, either in a normal debugger or an emergency debugger.

The `stopTimeSlicing` method provides a rather more managed way of stopping the time slicing process. This does send the `terminate` message to the time slicing process and then sets the global variable to `nil`. This method is available in the 'time slice process' method category. The method definition is:

```ruby
stopTimeSlicing
    "self stopTimeSlicing"
    TimeSliceProcess notNil
    ifTrue:[TimeSliceProcess terminate. TimeSliceProcess := nil]
```

So far we have set up the means by which a new, user defined process, can interrupt lower priority processes, and alter the process which will get run next. However, what we have not done is to define how this re-ordering of processes will occur.

The method `slice` in the method protocol *process state change* of the `ProcessorScheduler` performs this reorder. This is where the real meat of the time slicing operation occurs. The algorithm describing this method's operation is:

1. Find the first process priority queue which contains more than one process.

2. Remove the front process from this list and add it to the end of the list.
This is a very simple algorithm, but it works! The actual implementation of this algorithm is not quite as
tidy. It is presented below:

slice
| aPriority list |
| aPriority := self highestPriority.
"Find highest priority level with processes in it"
[aPriority > 0 and:
  [(quiescentProcessLists at: aPriority) size <= 1]]
    whileTrue: [aPriority := aPriority - 1].
"Reorder that priority queue"
aPriority = 0
ifFalse: [list := (quiescentProcessLists at: aPriority).
    list addLast: (list removeFirst)].

To test out the effects of the time slicing try evaluating the following in a Workspace:

ProcessorScheduler stopTimeSlicing.
ProcessorScheduler example inspect.
ProcessorScheduler startTimeSlicing.
ProcessorScheduler example inspect.

This executes an example method defined in the *time slice process* method protocol which produces two inspectors. This method forks two processes, each of which puts a number onto a shared queue. The inspectors are opened on the shared queues produced. In the first, all the 1's will come first and all the 2's will follow them. In the second the 1's and 2's will be mixed in together.

example
| queue |
|:---|
| queue := SharedQueue new. |
| [10000 timesRepeat: [queue nextPut: 1]] fork. |
| [10000 timesRepeat: [queue nextPut: 2]] fork. |
| ^queue |

This type of example is illustrated in the next section as part of a stand alone application.

## 31.4.2 Using the example

To see how the time slicing works evaluate the following Smalltalk in a Workspace.

| queue |
|---|
| ProcessorScheduler stopTimeSlicing. |
| queue := SharedQueue new. |
| [10000 timesRepeat: [queue nextPut: 1]] fork. |
| [10000 timesRepeat: [queue nextPut: 2]] fork. |
| queue inspect |

In the contents of queue you will find first all the 1's and then all the 2's. If you then evaluate:

| queue |
|---|
| ProcessorScheduler startTimeSlicing. |
| queue := SharedQueue new. |
| [10000 timesRepeat: [queue nextPut: 1]] fork. |
| [10000 timesRepeat: [queue nextPut: 2]] fork. |
| queue inspect |

then the 1's and 2's are mixed.

However, you should be aware that time slicing is dangerous in the current implementation of the Smalltalk user interface, as the following example illustrates:

ProcessorScheduler startTimeSlicing.
[100 timesRepeat: [Transcript show: 'Process 1'; cr]] fork.
[100 timesRepeat: [Transcript show: 'Process 2'; cr]] fork.

This will hang up Smalltalk because some resources are not protected against multiple access. (This is
why the example above used SharedQueue instead of a WriteStream)
### 31.4.3 Acknowledgments

Acknowledgments are made to Hubert Baumeister, of the University of Dortmund, Germany, who developed the original example. This was from an original idea put forward by Kent Williams of the University of Iowa.

## 31.5 Further reading

A good article on writing concurrent Smalltalk programs is [Hopkins and Wolczko 1989]. Lazy and future evaluators can also be implemented using these facilities. A good discussion on such evaluators can be found in [LaLonde and Pugh 1993].
# 32. The Metaclass Framework

## 32.1 Introduction

The metaclass concept is probably one of the most confusing parts of the whole of Smalltalk. This is partly due to the very confusing names used (for example, `Class class` and `Metaclass class`) but also because almost all of it is hidden from the developer. You are therefore only vaguely aware of it (if you are aware of it at all) during development. This means that developers do not need to understand it in detail and most people avoid trying to understand what appears to be a difficult concept if they don't have to. It also means that developers can only grasp what is happening abstractly, with little chance to see the mechanics of what is going on.

However, contrary to popular myth, the metaclass concept is actually not that difficult (if you can get around the terminology), although it can be confusing especially when its recursive definitions are encountered. We will however leave that aspect of metaclasses until right at the end. This means that you should hopefully gain at least an appreciation of what metaclasses about, even if the fine details of the implementation pass you by. In many ways, it is only an appreciation that you need (if you need it at all) to understand what you observe in the development environment.

As the basic concept being considered in this chapter is the concept of a class, Section 2 provides a review of what is meant by a class etc.

Metaclasses have not always been present in Smalltalk, they were only introduced into Smalltalk with the development of the Smalltalk -80 version of Smalltalk. This is essentially the version of Smalltalk which is used as the basis of commercial versions of the language (such as VisualWorks). Prior to that a number of (simpler) approaches were used. However, each of these provided fundamental problems which were overcome with the introduction of metaclasses.

Section 3 discusses the metaclass mechanism and how it works. As was stated before, it does this without going into the complexities of the implementation of metaclasses. This allows the casual reader to understand where metaclasses fit in and what they do without needing to understand the intricacies of the full metaclass inheritance hierarchy.

The classes `ClassDescription` and `Behavior` are introduced in Section 4. These classes encapsulate what it means to be a class and how classes do what they do. Section 5 considers the relationship between metaclasses, classes and the Metaclass class. This is not actually that complex, but can appear confusing at first sight.

A point to note before reading this chapter are the conventions used for Smalltalk, classes and instances. Remember:

* All Smalltalk code appears in a courier font, e.g. `Collection new`.

* All classes start with a capital letter e.g. `Set`, `Object`, `Array`.

* All instance names start with a lower case letter, e.g. `aSet`, `anObject`, `anEmployee`.

These conventions are adhered to rigidly below.

## 32.2 What are classes?

All classes are ultimately subclasses of the class `Object` (with the exception of `Object` itself). That is, a class inherits properties from its superclass (which in turn inherits properties from its superclass) up to `Object`. In turn every thing in Smalltalk is an object and every object is an instance of a class. On page 269 of the Purple Book [Goldberg and Robson 1989] the following statement is made:
> "There are two kinds of objects in the system, ones that can create instances of themselves (classes) and ones that can not."

This is a very important point, it highlights the fact that everything in Smalltalk is an object. That is, everything, including classes, are objects and can be sent messages (this of course means that classes are also instances of something, but what this is we will leave until later). However classes are special, they can create new objects called instances. Instances of classes however cannot create other instances (they must ask a class to do it for them).

In fact classes have only a very few roles in the system and these are essentially limited to:

* creating new instances,

* defining what those instances will do,

* holding class information (such as class variables).

Whereas instances hold application data and perform the operations defined by the (instance) methods held by the class. That is, the instance holds the data, but when it is sent a message it looks in the instance methods of its class for a method which implements that message. If no method is found in its class, then its superclass is searched for such a method. This search continues until the class `Object` is reached. If no method is found then the message `doesNotUnderstand:` is sent to the original receiver.

## 32.3 Classes and metaclasses

### 32.3.1 Metaclasses

As was indicated in the last section each class is an instance of a class. However we want each class to be able to behave in a different manner to any other class. Therefore each class must be an instance of a different class (as all instances of the same class must behave in the same manner). In Smalltalk -80 the concept of a *metaclass* was introduced. A metaclass is a special class, whose instance is a class. In general a metaclass only possesses a single instance (a class) and a class will be an instance of a single metaclass.

That is, a class is an instance of a metaclass and a metaclass defines how a class behaves. This means that it is actually in the metaclass that the class methods are defined and held. This means that when a class is sent a message, it looks in its metaclass for the method which implements the message. In effect, when you click on the class radio button in one of the various browsers in VisualWorks you are actually examining the classes' metaclass<fnref n="16" />.

If you are confused by the terminology try to think of it in this way:

> "A metaclass defines information about a class (hence the term meta)".

Metaclasses are not actually named directly, instead their names are a combination of the name of the class they define and "class". Thus the metaclass of `Collection` is `Collection class`, the metaclass of `Object` is `Object class` and the metaclass of a class called `Employee` would be `Employee class`. It is at this point that people begin to be confused by the terminology. We shall therefore attempt to recap.

* A class is an object which can create instances.

* A metaclass is a class which defines a class.

* A metaclass has only one instance (the class it defines).

* A metaclass is named after the class it defines concatenated with the word class.

<footnote n="16">¹⁶ In fact if you examine the `Browser` class you will find references to `self meta`. This is a reference to whether the user is currently examining the instance side (meta = false) or the class side (meta = true).</footnote>
In addition a metaclass cannot be accessed directly. It can only be accessed by sending the message `class` to a class. For example:

`Collection class.`

If you evaluate this and print the result, you will get the name of the Collection classes' metaclass, which is of course `Collection class` (which confusingly looks exactly like the expression which accessed the metaclass).

### 32.3.2 The Metaclass hierarchy

<figure><img src="image_147.png" /><figcaption>Figure 32.1: The metaclass hierarchy for the Collection classes</figcaption></figure>

As you are aware, the classes in the Smalltalk system form a hierarchy rooted on the class `Object`. Thus the class `Dictionary` inherits from `Set` which in turn inherits from the class `Collection` which ultimately inherits from the class `Object`. This means that when instances of these class are sent messages, the system can search up through the class hierarchy for methods which implement that message.

Metaclasses also possesses a metaclass hierarchy. In this hierarchy one metaclass can inherit from another metaclass. In Smalltalk -80 the metaclass hierarchy was constrained to mirror the class hierarchy. This means that if some class side behavior is defined in `Collection`, then it will be inherited by `Set` and `Dictionary` via their metaclasses. Figure 32.1 presents part of the metaclass hierarchy for the Collection classes. The net result is that if a class is sent a message, the system begins the search for a corresponding method in its metaclass. If it does not find it there, it then looks in the superclass of its metaclass. This process continues until either a suitable method is found or until the `doesNotUnderstand:` message is triggered.

Figure 32.2 illustrates the relationships between the two hierarchies. Note that dashed arrows represent instance relationships, whereas solid arrows represent inheritance. Please note the case used for each label. As can be seen from this figure, this means that each class is an instance of its metaclass and that the metaclass hierarchy exactly mirrors the class hierarchy. In the figure, the instance of the class `Dictionary`, labeled as a `Dictionary`, is presented in a rounded box, because it is an object which cannot create new instances. Therefore it is a different kind of instance. To make this distinction clear a different box style is used.
<figure><img src="image_148.png" /><figcaption>Figure 32.2: Class and instance relationships</figcaption></figure>

## 32.4 ClassDescription and Behavior

One point we ignored above was "what happens when we get to `Object?`". That is, `Object` is the root of the class hierarchy in Smalltalk and therefore `Object` does not inherit from any superclass. This is not a problem for the class hierarchy as `Object` encapsulates all the concepts associated with being an object. However, what happens in the metaclass hierarchy? One possibility is that `Object`'s metaclass, `Object class`, encapsulates all the concepts associated with being a class. However, in Smalltalk-80 a different and more sophisticated approach was adopted. (The reasons for adopting this approach only really become clear later when we discuss the recursive nature of metaclass, for the moment just accept that the following approach was taken).

In Smalltalk-80, `Object class`, the metaclass of `Object` inherits from a class called `Class` (See Figure 32.3). This allows `Object class` to define how the class `Object` should behave, while the concepts associated with being a class are encapsulated within `Class`. In particular, `Class` defines what instances of a class should look like and how they should behave. It also provides facilities which enable class variable names and pool (shared) variables.

<figure><img src="image_149.png" /><figcaption>Figure 32.3: The metaclass hierarchy up to Behavior</figcaption></figure>

In turn, `Class` inherits from `ClassDescription`. This class provides facilities for naming classes, commenting classes (and this is why we defined `commentTemplateString` here) and naming instance variables. `ClassDescription` was provided as a super class of `Class` so that another class called `Metaclass` (which we will consider in the next section) could also inherit these facilities.
<figure><img src="image_150.png" /><figcaption>Figure 32.4: The metaclasses for Class, ClassDescription and Behavior</figcaption></figure>

ClassDescription then inherits from a class known as `Behavior`. The class `Behavior` defines how classes should behave (for example how to create new instances). In particular it defines the minimum state necessary for objects that have instances.

Together these three classes define what a class is, how it should behave, how new instances should be created and what a class should look like. Figure 32.3 illustrates the metaclass inheritance hierarchy up to the class `Behavior`.

You may have noticed from the above class names, that `Class`, `ClassDescription` and `Behavior` are not metaclasses (i.e. they do not have class after their names). They are in fact classes, thus at the top of the metaclass hierarchy we find (not surprisingly) that metaclasses are classes after all. This raises two questions, firstly “do Class, ClassDescription and Behavior have metaclasses?” and “If metaclass are really classes, shouldn’t they be instances of something?”. In this section we will answer the first question, the second question is deferred to the next section.

As `Class`, `ClassDescription` and `Behavior` are classes, they are all instances of their metaclasses. This is illustrated in Figure 32.4. The metaclass of `Class` is of course `Class class` (the terminology can and will get worse!), the metaclass of `ClassDescription` is `ClassDescription class` and the metaclass of `Behavior` is `Behavior class`.

If you are comfortable with the description so far you have learnt most (if not all) of what you need to know to exploit the metaclass structure and to be sure that you are in fact dealing with `Class`, `ClassDescription` and `Behavior`. If you find that you become lost in the next section don't worry, much of what is described there is implementation level detail and overly convoluted.

## 32.5 The metaclass concept goes recursive!

### 32.5.1 What are metaclasses?

A question which was raised in the previous section (but not answered) was “If metaclass are really classes, shouldn’t they be instances of something?”. The answer to this question is “yes”, just like any class, they are in fact an object and objects are all instances of some class. The next question then is, “of what class is a metaclass an instance?”. The answer this time, is the class `Metaclass` (note the capitalization and font).

That is, all metaclasses (such as `Collection class`, `Object class` and `Set class`) are instances of the class `Metaclass`. This is because all metaclasses have the same behavior. They define the structure, definition and behavior of a class. Each subsequent class may have a different
behavior, but from the point of view of the metaclass, all classes are constructed in the same way, are structured in the same way (i.e. they have class methods, class instance variables and class variables) and all require the same set of operations (i.e. they must be able to construct instances).

### 32.5.2 What is metaclass an instance of?

<figure><img src="image_151.png" /><figcaption>Figure 32.5: Instance relationships between instances, classes and metaclasses for array</figcaption></figure>

Metaclass, being a class, must also be an instance of something. Following the standards laid down about it is therefore an instance of its metaclass. This metaclass, like all other metaclasses, has its name derived from the class, it is therefore called *Metaclass class*. However, every metaclass is an instance of *Metaclass*, thus the *Metaclass class* is an instance of *Metaclass*. This is the first point of circularity in Smalltalk and it is worth summarizing:

* All metaclasses are instances of *Metaclass*.

* The metaclass of *Metaclass* is *Metaclass class*.

* *Metaclass class* is a metaclass, it is therefore an instance of *Metaclass*.

* Therefore the metaclass of *Metaclass* is an instance of *Metaclass*.

This is illustrated in Figure 32.5. This figure shows that an object such as an array is an instance of the class *Array*. In turn *Array* is an instance of its metaclass *Array class*. This metaclass is an instance of the class *Metaclass*, which is an instance of its own metaclass *Metaclass class*. And as has been said, *Metaclass class* is an instance of *Metaclass* (see what I mean about the terminology!).

### 32.5.3 Instance relationships for classes and metaclasses

<figure><img src="image_152.png" /><figcaption>Figure 32.6: Instance relationships</figcaption></figure>

To complete the explanation being given, consider Figure 32.6. This illustrates the *instance relationships* between classes, their metaclasses, the *Metaclass* and the *Metaclass class*. Note
that no distinction is made between a class being an instance of another class and a user generated instance of the `Dictionary` class.

### 32.5.4 Class inheritance

A point we have still not covered is what does the class `Metaclass` inherit from? Remember all classes (except `Object`) have a superclass and `Metaclass` is no exception. `Metaclass` inherits from `ClassDescription`, this is because the structure of classes and metaclasses are very similar. For example instances of both `Class` and `Metaclass` can have methods. In turn, the metaclass of `Metaclass`, (i.e. `Metaclass class`) follows the standard laid down and it inherits from the `ClassDescription class`. This is illustrated in Figure 32.7.

As `ClassDescription` is a subclass of `Behavior`, it also means that both `Class` and `Metaclass` inherit from the facilities provided by `Behavior`. This means that instances of both `Metaclass` and `Class` can create new instances etc. (Remember `Behavior` provides all the protocol for making new instances so this is not surprising).

<figure><img src="image_153.png" /><figcaption>Figure 32.7: Class inheritance</figcaption></figure>

We are now left with the class `Behavior` and what it inherits from. All other classes have been accounted for. What then does `Behavior` inherit from? It inherits from the class `Object`. This closes the loop and ensures that all things in the whole of Smalltalk are objects (i.e. at some point their class inherits from `Object`) whether they are class, metaclasses or ordinary instances.
### 32.5.5 The whole enchilada

<figure><img src="image_154.png" /><figcaption>Figure 32.8: Combining both the instance and class relationships</figcaption></figure>

The last two sections have considered the instance relationship and the inheritance relationship between classes in Smalltalk respectively. Each of these in isolation isn't too complicated, however when you put the two together you obtain a diagram such as that illustrated in Figure 32.8.

This figure illustrates the instance and inheritance relationships between classes and metaclasses. As can be seen from this diagram the overall structure is quite complex. However, if you study it closely you should find that it does make sense. Even when there appears to be the potential for excessive circularity it can be seen that this is not the case. There is one point of circularity which should be noted, that is an *Object* is an instance of *Object* class which (eventually) inherits from *Behavior* which inherits from *Object*.

## 32.6 Further reading

See Chapters 5 and 16 in the *Purple Book* [Goldberg and Robson 1989] for an introduction to metaclasses and a detailed description of the class *Class*, *Metaclass*, *ClassDescription* and *Behavior*. However, the actual description of the metaclass concept and the diagrams presented with it are a little confusing. Also see Chapter 26 of [Hopkins and Horan 1995] for an excellent introduction to metaclasses.

## Part Seven

# The Future
<figure><img src="image_155.png" /></figure>
# 33. The Future for Object Technology

## 33.1 Introduction

This chapter is structured in the following manner: we first consider issues directly relating to the future of the Smalltalk language and then the type of object oriented development toolkits which are, and will be, available. We next consider the impact of the internet on object technology. We then briefly discuss the development of object oriented databases and then address Smalltalk's role as a training environment for object technology before concluding by considering very briefly the future of object technology over the next five years.

## 33.2 The Smalltalk language

The Smalltalk language is unlikely to change a great deal for the new ANSI standard being produced by the X3J20 standard committee. This committee was formed in late 1993 and draws its members from both the user and vendor communities. This standard is necessary as more and more vendors are producing Smalltalk based development systems which, while similar, all possess (significant but subtle) differences. Although the merger of the two largest Smalltalk vendors ParcPlace and Digitalk in 1996 could be seen as resulting in the creation of an enforceable standard, other vendors could still "go their own way".

However there are other aspects of the Smalltalk language which need to be addressed, some of which are fundamental to Smalltalk and others of which are technology oriented. Each of these areas will be considered below.

### 33.2.1 Smalltalk issues

There are a number of language issues which Smalltalk must address if it is to survive and prosper into the next century. All of these are related to providing better support for large scale, commercially critical systems. Such systems require:

* **Non-interpreted implementations**: All commercial version of Smalltalk rely on the use of a virtual machine which executes byte codes. The byte codes are the "compiled" version of the Smalltalk source code. This means that Smalltalk is compiled into an intermediate language which is then "interpreted" by the virtual machine rather than being compiled into a native code. The result is that Smalltalk does not produce a true executable image which generally results in significant performance and memory overheads.

* **Class-based version control**: Within a software development project, different team members will be developing different parts of the system. In many cases they will maintain their source code using a source code control systems such as SCCS under UNIX. This means that all the source code control operations are outside of the Smalltalk system and require external intervention. For example, if a developer within a project using SCCS, wishes to see how an old version of a class would interact with a set of newly defined classes, they must leave VisualWorks, retrieve the old version of the class from SCCS, file it into VisualWorks, probably having removed the newer version of the class from the image to ensure that no additions remain. When they have finished performing these tests they must then retrieve the new version of the class. Such version control of classes and methods should be inherent to the development environment rather than a third party after sales add-on.

* **Team-based development support**: Smalltalk was originally conceived as a language and development environment for a single user. It therefore has inherent weaknesses when it comes
to team development. At present if members of a development team wish to share their work they must file out (all) the relevant classes and methods from their own images and file in those from their fellow workers. This can be problematic as well as cumbersome. This problem stems from the very nature of the image in which all the "source code" is held and within which development takes place. A fundamental change in the way that the image works is required.

* **Typed variables**: Smalltalk is a dynamically typed language. That is, a variable's type is determined by the type of object that it holds. This is all very well for rapid prototyping and for small single user developments, however for large projects which must exist for significant periods of time, this can result in disaster. For example, "type mismatches" cannot be detected at compile time and will only manifest themselves at run time. This places a huge burden on testing which must now catch such mismatches. In addition the performance of a dynamically typed language can be lower than that of a statically typed language as the run time system must now perform various checks which could otherwise be performed at compile time.

* **Improved exception management**: At present Smalltalk possesses only very rudimentary exception handling. If the developer has not defined how the exception should be caught it is merely presented to the user. This is acceptable for a single user/developer system, however for delivered systems this is unacceptable. Even the facilities that are available are extremely limited. For example, class level rather than block or method level support is required, such that if a particular type of exception occurs anywhere within an instance of a class (or one of its subclasses) then that exception is handled cleanly and in an appropriate manner.

* **Private methods**: In Smalltalk all methods are publicly available, that is any object can send a message requesting that the receiving object perform any of the defined methods. In general Smalltalk developers place those methods which are not intended for external use in method protocols such as private (or private -<some-additional-description>). However this is only convention and there is no system support for these "private" methods. Other object oriented languages such as C++ and Java do support the definition of private and public methods. Indeed these languages take the concept of private and public further. For example, in Java [van der Linden 1996] there are a number of classes of access indicated by keywords:

1. public - world access.

2. protected - accessible to any object in the current package or any subclass in any package.

3. default - any class in the package (A Java package is a group of classes which are to be bundled together. They are essentially the same as libraries in C++).

4. private protected - class / subclass access only.

5. private - accessible to the current class only.

Of course some of the above issues are being addressed by current research (for example [Feigenbaum 1995]) however there appears to be little interest in following this lead from the vendor community.

### 33.2.2 Technology issues

There are a number of technology based issues which will affect Smalltalk's popularity in the coming years. These are less related to Smalltalk itself and more to the way in which software is, and will be, developed.

The majority of software today is developed for use on PCs running either Windows 95, Windows NT or Windows 3.1. Therefore Smalltalk needs to be able to easily and simply interact with these environments. For example, explicit support for OLE and dynamically linked libraries is a must.

In the future it is likely that the influence of the World Wide Web (or Web) and the internet will continue to grow. Smalltalk vendors must provide facilities which will allow Smalltalk to take advantage of this (ParcPlace-Digitalk have already produced a product called VisualWave which is a VisualWorks based Web server).

Object sharing and notification must be made significantly easier. CORBA (see [Ben-Natan 1995] for a summary of the CORBA standard and [Orfali et al 1995] for an excellent compendium of distributed object technology including OLE, OpenDoc as well as CORBA) while providing a possible infrastructure for such object sharing results in large cumbersome ORBs (CORBA stands for the Common Object Request Broker Architecture. It is a specification for an ORB (Object Request Broker) which allows distributed objects within different systems to communicate. Simpler and easier to use
solutions are needed which suit the require ments of less technically complex systems, such as a
database server which is accessed by a small number of interacting Smalltalk clients.

Improved support for deploying applications is required. The process of removing as many system classes as possible without damaging the application's operation is still largely an art rather than a science. VisualWorks 2.5 does give greater support for this, however it is still severely limited in its operation.

Finally, there needs to be a convergence between the di fferent Smalltalk dialects. This will happen to some extent through the new ANSI standard. However, if this standard does not cover issues such as the user interface, database access, web access, the use of dynamically linked libraries and OLE, then it will have only limited success.

33.3 Object oriented development toolkits

For Smalltalk to maintain its position as a mainstream language it must be supported by appropriate development tools, as well as by a number of language vendors. The merger of Digitalk and Parcplace systems raised the prospect of the emergence of essentially a single language vendor (as ParcPlace and Digitalk between them accounted for the majority of Smalltalk system sales). This has been an impediment to a language's success in the past. F or example, developers are unwilling to commit to a language which, on the demise of their system supplier, forces them to re -implement the whole system in a new language. However IBM have entered the market with their range of Smalltalk products thus alleviating the situation to a certain extent.

However we are still left with the issue of the range of development tools and toolkits available. It is
possible to classify object oriented development toolkits into a number of categories:

* **Object oriented language compilers and linkers**. These tend to be command line programs which read in a source code file and produce object files which are then combined with other object files to create a stand alone executable. They are typically used in an Edit -Compile-Link-Execute cycle in which the various tools used are poorly integrated (if they are integrated at all).

* **Object oriented application development environments**. Object oriented Application Development Environments (or OOADEs) are comprehensive development environments that not only possess highly integrated development tools but also provide a far greater level of developer support than the basic language compilers. For example, database access, use interface construction, code generation and libraries of reusable components. Typically OOADEs exploit an iterative development cycle in which the developer writes some code, compiles it in-situ and executes it before writing some more code.

* **Object oriented CASE (OOD methodology-based) tools.** OO CASE tools differ from the OO ADEs because they support one or more OOD methodologies. The most common OOD methodologies used with OO CASE tools are OMT and Booch. These two accounted for over 50% of OOD methodologies used world wide in 1995. Given this, it is likely that the Unified Modeling Language (UML) will have a significant impact in the future, as it is the inheritor of both OMT and Booch.

There are in fact two different types of OO CASE tools available: OO analysis and design tools and OO Integrated CASE tools. The former act as diagramming tools while the latter are model-based code generating tools. Most of the code generation tools support C++ although versions for Smalltalk have been appearing since the end of 1995. This is now a significant market which increased in the US by 82% in 1995 to be worth about $138 million.

Smalltalk examples of each of these can be identified. For example gnu -Smalltalk falls into the first
category, while VisualWorks itself falls into the second. There are also a growing number of Smalltalk
based OO CASE tools. For example, Rational (probably the most influential OO CASE developer
having Grady Booch, Jim Rumbaugh and Ivar Jacobson working for them) has a ve rsion of its product
ROSE for Smalltalk (It also produces versions of Rational ROSE for C++, SQL Windows and Ada).

However it is worth noting that although OO CASE tools are the fastest growing product area, this is an area in which Smalltalk has been a re latively late entrant. OO CASE tools first started appearing commercially , in any number, around 1992. It was three years before many of these tools offered direct
Compatibility (or code generation) for Smalltalk. For Smalltalk to continue as a commercial success it is essential that it gains a similar level of support in this area as C++.

## 33.4 The internet and objects

The world wide web (or just the Web for short) is one of the phenomena of the last few years. It is set to revolutionize the way we think about computers and computing. However, at present most information available on the web is in the form of static web pages. These are useful in providing information but are fairly limited in their ability to do much more. Java has of course allowed Web pages to possess at least some dynamic element, however the majority of Java applets on the Web make little cartoon characters do something. To gain the full benefits of the Web it is necessary to be able to connect applets, downloaded from the Web, into corporate databases or to existing programs. Such an ability will open the Web up to a huge range of applications both within and between corporations.

Java, of course, has already guaranteed that object technology will play an important role in the development of such applications. Java is in many ways just another object oriented language, which like Smalltalk, is not compiled into an executable but into byte codes which are then "executed" by an interpreter (or virtual machine). Thus any Java applet is an object or set of objects which communicate with each other via message passing. Thus these applets should be capable of communicating, relatively easily, with a distributed object system. Indeed developments are already under way to link Java applets to CORBA compliant ORBs, and to OLE/COM.

To simplify this sort of task, special OO WEB site development tools will be (and are being) developed. It is also likely that many of the existing OO CASE tools will provide Web additions so that they too can be used with the Web and for Web development.

However, which language will dominate, and which type of distributed system will be adopted, are two different questions. Java will certainly be the dominant Web language, although there is no great reason why Java should be any better as a Web language than Smalltalk or any other interpreted OO languages such as Objective-C or Eiffel, other than the fact that Java got there first and has the backing of both Netscape and Sun. However, in early 1996, ParcPlace-Digitalk released VisualWave. This is an application development environment (ADE) for building live applications on the Web. VisualWave runs on VisualWorks and hides all the HTML (Hyper Text Markup Language) and CGI (Common Gateway Interface) details from the developer. Instead, the developer can concentrate on creating Web applications in a Smalltalk environment. This allows the user to access multiple databases, use interactive window building tools, Smalltalk classes and the VisualWorks browsers to develop applications. At present VisualWave relies on the use of a CORBA compliant ORB, however it claims that it will be able to access OLE components soon.

It is interesting to compare and contrast Java and Smalltalk. Smalltalk appears to be the better OO language for the internet as it is not a hybrid language and has many features built into it which would work well with the Web. This means that it is likely that companies which already have significant Smalltalk experience will stick with Smalltalk and use VisualWave, although many others will swallow the hype surrounding Java, and go with it.

The question of which distributed object technology will be adopted is more complex. OMG would certainly like CORBA to be adopted as the accepted standard, while Microsoft would prefer their own OLE/COM infrastructure standard. An open question is what will Netscape do? It is probable that Netscape will do both. For example, Sun have already linked Java with CORBA and Sun and Netscape are closely linked, but a great deal of the world uses Microsoft products.

## 33.5 Object oriented databases

An object oriented database system is one which relies on an object-oriented view of the world, that is, uses classes and objects as the basic storage mechanism rather than forms and tables. In general these databases are also quite flexible about the type of data they hold including text, programs, graphics, video and sound. However OO databases have been fairly thin on the ground until recently. The main players in this field have tended to concentrate on Smalltalk based systems. Either providing Smalltalk binding or in some cases implementing the system in Smalltalk and treating Smalltalk as the database
scripting and query language to use. Recently however, a great deal of interest has been shown in using
OO databases with the Web.

Web developments are not only based around a variety of different data types, they also require the
ability to navigate easily around data in a domain model. Many OODB vendors (as well as many users)
are coming to the conclusion that OO databases are ideal for supporting a HTTP server. By storing the
Web site within the OO database the process of exchanging data with the database, and modifying the
Web pages is simplified.

This trend is likely to increase significantly in the future. It is already the case that other OO
database suppliers are adding Java interfaces or making their systems Web compliant. It is also likely
that the Web will act as the motivating force which will force many organizations to adopt OO
database technology (as opposed to relational database technology).

33.6 Smalltalk as a training environment

It is likely that Smalltalk will reach a point in the commercial sector where its use does not increase. At
what level this will occur is still unclear, however I believe that Java is going to have a greater impact
on the use of C++ than Smalltalk. If anything, I suspect that Java will help to interest people in OO
languages including Smalltalk. At this point I believe that Smalltalk’s strengths as an educational
language will come to the fore.

Far too many people believe that it is possible to move from a procedural development language, such as C, to an OO language just by reading a book on C++. The result is that they develop C programs but maintain their data within objects. I myself have been involved in discussions with developers who have claimed that object technology is a waste of time because they did not accrue the benefits claimed. When pressed it is almost always that case that they failed to invest in appropriate training for their staff. This was their mistake.

The transition to object technology is not an easy one. Indeed it becomes harder the greater the level
of experience of those trying to make the change. This does not necessarily have anything to do with
their ability to adapt to new ideas, rather I believe it is to do with the fact that they have a very firm
grasp of one paradigm where as less experienced software developers have a poorer grasp of (for
example) the procedural paradigm. It is therefore necessary to include in the first object oriented
development attempted by an organization, a suitable training budget. This budget needs to be seen as
an investment in the future, rather than a cost of the actual project involved. In addition it should not be
seen as a language programming exercise. The best approach is to view it as a training in the philosophy
and techniques of object technology. The aim of such a training is not necessarily to educate those
involved in the use of the tools to be used on the actual project (such as OO CASE tools and the OO
language to be used). Such an approach will allow the staff involved to explore the concepts rather than
worrying about a particular syntax and how it differs from what they are used to.

Of course educating software developers in abstract concepts is only of limited use, therefore such
training courses should re-enforce what is being taught with practical experience of a pure OO language
such as Smalltalk. After all it is not possible to write anything in Smalltalk without using objects and
message passing. In addition it is easier to spot conceptual problems in Smalltalk (as evidenced by
students attempting to write the main program or worrying about procedures rather than objects).

I therefore believe that Smalltalk will have a concrete future as an educator as well as a practical OO
development environment. Indeed it may well have a greater influence as an educational language
allowing organizations to migrate to object technologies in as painless a manner as possible.

33.7 Object technology: the next five years

What will happen to object technology over the next five years? This is both an interesting and a
difficult question. Object technology is certainly gaining an ever increasing share of the market for
commercially developed systems, however there is still a great deal of resistance to it in many quarters.
This resistance is sometimes due to ignorance and sometimes due to bigotry. In either case it requires
someone to champion its cause in the affected organizations. However the Web is here, and despite the
hype, is likely to be a major factor during the next ten years.
Thanks mostly to Java, object technology is seen as the developer's Web technology. This therefore means that it is likely that much of the development in object technology will be Web driven (we have already considered some of its effects above). This will probably continue to grow and may have both a positive and detrimental effect. The positive effect will be that many new and existing companies will adopt object technology, many other companies will move to support their requirements and many new start up companies will be created. Over time many of these companies will close down again only to be replaced by other small start up companies. It is within these companies that many of the most innovative ideas will probably be generated (consider Netscape as an example). This will be a very creative and dynamic time.

However there are two possible results of this. One is that object technology becomes so successful that companies such as Microsoft consider it a part of their core business and move into the market with such force that they come to dominate. I have always believed that monopolies (or virtual monopolies) are a bad idea and certainly tend to be bad for any industry. The other concern is that object technology becomes so tightly linked to the Web in people's minds that the technology providers ignore other aspects of the computer world and focus solely on the Web (which I believe would be a mistake). Such a close binding might have a short term benefit, but let us hope that when the Web bubble bursts or when the next great new thing comes along, object technology is not left behind with the Web and ignored.
# 34. Appendix: The Smalltalk Language Syntax

## 34.1 Basic syntax

### 34.1.1 Statement separation

Achieved in Smalltalk by the *period* or *full stop* rather than the semi-colon as in Pascal or C. For example:

Transcript show: 'Hello World'.
Transcript show: ' John'.

Although it is unnecessary to put a period at the end of the last line of code, as in Pascal it is a good idea.

### 34.1.2 Assignment operator

The assignment operator is the colon equals combination as in other languages such as Pascal. For example:

a := 2 + 4.

This operator is not a "copy" operator and thus may result in two variables referencing the same object. Not that `:=` is not a message as variables are not objects (whereas `+` is a message as it relates to two objects even if one is contained within a variable).

Further example are:

oldIndex := 1.
newIndex := oldIndex.
myArray := # (1 2 3 4).
myName := 'John Hunt'.

Assignments return values (like other expressions), so that several assignments can be made together:

nextIndex := newIndex := oldIndex.

### 34.1.3 Comments

Comments are defined using `""`. Everything between the double quotes is treated as a comment. Note that comments cannot be nested in Smalltalk. This can be awkward if you wish to comment out some code for later.

### 34.1.4 The return operator

This operator is used to return a value from a method. By default a method will return the object that the message which triggers the method was sent to. However, this can be altered using the return operator `^`. For example:

^24

would cause a method to return the value 24. Note that the method will "return" as soon as it encounters a return operator. It is therefore possible, although not necessarily a good idea, to have more than one
return operator in a method. Thus allowing a method to return from different points depending on the
execution path taken through the method.

**34.1.5 Cascading**

The cascade operator, represented by a comma ( , ) can be used to send a series of messages to the same
object (which is only referenced once). For example:

Transcript cr.
Transcript show: 'John Hunt'.
Transcript: tab.
Transcript show: '1995'.
Transcript cr.

Can be re-written as:

Transcript cr;
    show: 'John Hunt';
tab;
    show: '1995';
cr.

**34.2 Literals and variables**

**34.2.1 Literals**

Literals are constant objects such as numbers, characters, strings, symbols etc.

Numbers are a sequence of numeric characters with an optional decimal point and an optional minus
sing. Example of numbers are:

8 12.7 -44.7 0.0009

In Smalltalk a number is positive unless otherwise stated. there is therefore no need for a unary
plus sign. Numbers can also be represented in other bases, by preceding them with a radix and
the letter “r”:

6r145 8r5E

Characters are individual letters and are distinctly different to a string containing only a single letter.
They are represented by a single character preceded by a “$” symbol. For example:

$a $d $' $+ $4

Strings are collections of characters encompassed within single quotes. They can possess spaces, under
bars etc. For example:

'Hello World'

Symbols are special objects that represent unique entities in the Smalltalk system. These are
represented using a leading the hash (#) symbol.

#temp #john

**34.2.2 Variables**

Variable names describe accessible variables. Variable names are identifiers made up of letters and
digits with an initial letter:

someObject MyCar totalNumber
A capitalization convention is used consistently throughout the standard image. Most Smalltalk programmers adhere to this standard which it is therefore advisable to follow:

* Private variables (instance variables, temporaries) start with an initial lower-case letter.

* Shared variables (class variables, global variables, pool variables) start with an initial upper-case letter.

Message selectors should also start with a lower case letter. For both variable names and message selectors, if the name is a combination of two or more words, the convention is to capitalize the first letter of the second word onwards. For example:

displayTotalPay returnStudentName

### 34.2.3 Pseudo variable names

A pseudo variable name refers to an object which cannot be changed; these include:

* `nil`. A value used when no other value is appropriate, such as `un initialized` variables. `nil` is the sole instance of class `Undefined Object`.

* `true`. Represents truth. The sole instance of class `True`.

* `false`. Represents falsehood. The sole instance of the class `False`.

True and False are subclasses of `Boolean` which implements Boolean algebra and control structures.

In addition there are two pseudo variables whose value changes depending upon the context. They are therefore not constants, however the programmer has no ability to change their value.

* `self`. This refers to the receiver of a message i tself. It literally means "the object within which the method is executing". It is used to send a message to the object requesting the another method defined on the object is executed.

* `super`. Also refers to the message receiver, but the method search starts in the superclass of the class in which `super` is used. This is often used if the functionality of a method is to be extended rather than overwritten. For example:

myMethod: anObject
new code before super.
super myMethod.
new code after super.

There is also a pseudo message, which just returns the receiver of the message as the result of evaluating the message. This message is `yourself`:

* `yourself`. A message which returns the receiver of the message. It can be used in any situation, however its most common use is in a cascade of messages, where it is necessary to return the original receiver of the cascaded messages.

### 34.2.4 Declaring a variable

To declare a *temporary variable*, place the variable to be declared between two bars, e.g. `| x y z |` indicates that the variables x, y and z are temporary variables.

If you reference an *undeclared variable* the system will assume you wish to declare a new global variable and do so. Global variables should, by convention, always start with a capital letter. They can be deleted by looking at the Smalltalk system dictionary and deleting the appropriate entry.
## 34.3 Classes and methods

### 34.3.1 Defining a class

The structure of a class definition is:

```
NameOfSuperclass subclass: #NameOfClass
    instanceVariableNames: 'instVarName1 instVarName2'
    classVariableNames: 'ClassVarName1 ClassVarName2'
    poolDictionaries: ''
    category: 'Visual Organiser'
```

Where

* `NameOfSuperclass` is the parent class of the class to be defined.

* `NameOfClass` is the name of the class being defined. (Note that at this stage it does not exist and must therefore be preceded by a `#`).

* `instanceVariableNames` is used to list the instance variable to be used with this class.

* `classVariableNames` is used to define the class variable to be used with this class.

* `poolDictionaries` defines the pool variables to be used with this class.

* `category` defines the category in which this class will be placed.

Note that this definition may not define all the variables associated with this class, for example, it may have inherited instance variables from its parent.

### 34.3.2 Methods

The structure of a method is:

```
messagePattern: argument1 additionalPattern: argument2 ....
    "comment"
  | temporaries |
  | statements |
```

Where

* `messagePattern` and `additionalPattern`: represents the name of the method. Notice that the method name is divided up amongst the arguments and that a part of the message name which precedes an argument has a trailing colon `':'`.

* `arguments` the names of arguments in the message pattern are accessible within the method.

* `"comment"` is a comment describing the operation performed by the method and any other useful information.

* `| temporaries |` is used to define variables which are local to the method. They must be declared at the beginning of the method (just after the message pattern) and are initially `nil`.

* `statements` represents any legal set of Smalltalk statements. These statements are used to implement the behaviour of the method.

### 34.3.3 Message expressions

Message expressions describe messages to receivers. The value of the expression is determined by the method it invokes. For example, the following is a message expression:

```
newStatus := thisPerson marries: thatPerson
```

This expression is made up of an assignment and a message expression. In turn the message expression is made up of a receiver, a message selector and an argument:

* `thisPerson` is the receiver