Now that we've looked at the principles behind MVC, and considered its basic architecture, we will look at some of the details behind how it is implemented in VisualWorks. If you're interested in understanding all the details you should look in your manual, or browse the system code. Be wary though if you are familiar with programming in another window system, Smalltalk works quite differently from MS-Windows, the X window system or the Macintosh. In particular, the window system is polled, not event-driven. This may change in the future, but for now you should be aware that it makes programming with the Smalltalk UI different from most other window systems.
Look carefully at the next diagram. It shows the relationships between the model, view and controller objects. The view has two very
Chapter 9
The relationships between model view and controller objects.
important instance variables (as well as many others, of course). There is a variable called model which contains the model the view is displaying, and a variable called controller, which contains the controller used to modify the model when the user uses the mouse or keyboard to interact with the system. The view also has variables which point to its 'container' in the window (the larger view it is probably a part of), and to its 'components' (the things it in turn contains).
Similarly, the controller has two important instance variables shown in the above diagram—model and view. These variables contain (or 'point to' if you prefer to think of it in that way) the model and the view objects respectively.
Notice how the view and the controller are fully aware of each other's existence, and of the existence of the model. This means that the view is able to ask the model (because it knows which object it is) for the data it is supposed to be displaying on the screen. Likewise, the controller is able to send the model messages telling it to perform operations when commanded by the user through the mouse or keyboard.
The model does not have instance variables containing the view or the controller (it has plenty of others of course!). Instead, the view has made itself a dependent of the model. This means that (provided the model uses the 'changed' messages which are part of the dependency mechanism) the view will get to know if the model changes in some
The MVC Architecture way, and can reflect the result on the screen. The model meanwhile, remains blissfully ignorant of which view or views are being used to display it.
This arrangement has a number of effects. Firstly, views and controllers are tightly linked together and can co-operate extensively. For example, when a controller receives a mouse-click, it may know the co-ordinates of the click, but will have to ask the view what object is being displayed there, in order to decide what action to take. It also means that views and controllers always come in pairs. In fact, when you make an instance of one of the many views in the class library, you will get an instance of the appropriate controller class automatically attached to it, without really noticing it. Most views in the system know what class of controller should go with them.
You might ask why the jobs of the view and the controller are not combined into a single object. This is a good question, and there are at least two answers. First, having them separate makes it possible to combine them in different ways. You might use the same controller, but change the view to display the model's data differently (to get a different look). Alternatively, you might use the same kind of view, but change its controller to work differently with the mouse (to get a different feel).
The other answer to the question is that separating the view and the controller allows them to inherit from different classes. This means that the view functionality and the controller functionality can be structured quite differently in the class hierarchy. This technique of composing functionality from combinations of instances is actually one way of overcoming Smalltalk's lack of 'multiple-inheritance' (where a class can inherit not just from one direct superclass, but from several superclasses at the same level).
The other result of the way the model, view and controller are structured is that the model is not directly aware of the view (or of the controller for that matter). This means that a different view/controller combination could be plugged into the model to display and interact with it differently, without the model having to be changed at all. Also, because dependency is used to connect the view to the model, the model can in fact have more than one view/controller at the same time. As many views as want to, can become dependent on the model, and display its data simultaneously. They will all receive 'update' messages whenever the model changes (provided it sends itself the right 'changed' messages of course), and they will all know to redraw themselves if necessary as a result of the change.
Chapter 9
The messages which pass between model, view and controiler.