========================================= Notes for: 6 May 1996 ========================================= Administrative: Two-day extension to the homework. Next assignment ready soon.... Smalltalk quiz in section next week (Tuesday). ========================================= Today: The Model-View-Controller architecture Programming the interface ========================================= General notes on Model-View-Controller MVC is a fairly abstract, simple idea. Basically it just says that the data object (the "model") should be programmed without depending on what output interface ("view") and input interface ("controller") are slapped on top of it. In other words, you should be able to take your code for an Employee data base, build one GUI on top of it, then rip that interface out and slap a new one on, without having to change the database code at all. There is a supposed distinction between a view and a controller, but I've never seen that distinction as important. What is really important is separating the model from the interface. We started by looking at the model for a bank account class. That should have looked very familar, except maybe for three things: -- we built "setters" and "getters" for every instance variable, -- any place in the code that wanted to change an instance variable had to do so by calling a setter (rather than saying "variable := value" directly) -- each setter sent an abstract message indicating that its instance variable had changed state. These looked like balance: aValue balance := aValue self changed: #balance The changed: #balance message is sent to the interface, which realizes that instance variable balance has changed, and decides what part of the display interface should change as a result. That's all we need to say about the model. Next we turned to building the interface. ================================================ Interface design. 1. Prototyping the screen We started at the "widget" level, doing so by opening a "canvas builder" from the VisualWorks top menu. You see a palatte that allows you to place widgets on the canvas and move them around. Some widgets are totally passive: labels, lines, boxes. Others will correspond to output-only boxes (the account number and balance). Still others will be input/output text boxes (the name and address). And finally there will be some that have a non-textual representation of the data (the radio buttons). The first step then is to place all the widgets on the canvas and align them to your satisfaction. Next it is a good idea to save this canvas, a process called "installing" it. The specification for a canvas is actually stored as an instance method in a class. You make up both the name of the class and the name of the method. But the strong convention is that if the model has class name Account, the interface will have the class name AccountInterface, and the method will be stored under the name windowSpec. The first time you install the canvas you will be creating the AccountInterface class, and you will be asked what category to save it in. Convention is to store it in the same category as your model, that way you can file them in and out at the same time. You also want to select the "application" check box, which is a just a note to the Resource Manager identifying this new interface. After installing your canvas you can look at the new class AccountInterface, and browse the class method windowSpec to see what the code associated with a canvas is. You will see an entry for every widget on the canvas. You can also go to the resource manager (a button on the main VisualWorks menu bar) and notice that the AccountInterface->windowSpec is now in the resource directory. This will be useful when you want to edit the canvas again. Next we began connecting up the interface with the model. (At this point there is no connection whatsoever.) One important thing to note is that certain fields in the interface need some "local space" to store information. Name, address, and deluxe/basic, for example: when you type into these fields, you are not entering information directly into the model. Only when you push the "action buttons" marked CHANGE or RESTORE should data be passed from the interface to the model or vice versa. On the other hand, the "Balance" and the "ID Number" fields do not need any local storage since you can't write into them. They can get their information directly from the model, and every time the model's instance variables balance and number change, the associated fields in widgets should change too. We are beginning by looking at the Name/Address/Basic/Deluxe fields, and the first thing to do is to associate an "aspect" with each one. An aspect corresponds to an instance variable in the class AccountInterface, where we will store local information for each of those widgets. We assigned an aspect for Name and for Address, the conventional names are nameValue and addressValue. We assigned the same aspect name, typeValue, for the Basic and the Deluxe radio buttons, since they are associated with the same piece of information in the model. The last thing we did was assigned symbol values for the Basic and the Deluxe values: we gave the symbol #basic to the first and the symbol #deluxe to the second. Recalling that "typeValue" is now an instance variable in AccountInterface, what this means is that whenever the Basic radio button is selected, the instance variable typeValue will be bound to the symbol #basic, and whenever the Deluxe widget is selected, the variable typeValue will be bound to the symbol #deluxe. The interface will take care of all this for us automatically.