[Infusion-users] MVC and Infusion
jas at northwestern.edu
Fri Jul 2 22:23:05 UTC 2010
I am new to Infusion, and so I may be interpreting things incorrectly. If so, please excuse these comments. This is in response to this page:
In the classical MVC design pattern, an object was called a "model" because it was an object-oriented model of a domain object and its behavior. The goal was to separate concerns about behavior (business logic) from the details of the user interface. You can think of controls as being the read-outs and leavers on a (potentially) complex but abstract machine called the model. In fact if you look at a Smalltalk image, the class Model is one that handles registering listeners and broadcasting changes.
In the classic arrangement controls call methods to query visible state and modify model objects. Likewise when a model was changed, it would broadcast a description of the change to listeners. That way model logic would be all about the domain and would not have to reflect any knowledge of the specific controls and read-outs attached. Views and controls would be about visually interpreting and allowing the user to modify model state by calling public methods while not having to deal with the business logic. If you wanted a new view or control, you could write one and attach it without altering the model's logic.
Infusion, on the other hand, by putting the responsibility of broadcasting model changes in the hands of visual controls (components) is introducing two issues: 1. It makes it difficult to have a many-to-one or one-to-many relationship between model objects, views, and controls, and 2. Separation of concerns becomes more difficult.
1. One-to-Many Relationships Between Models and Views
For example in my zooming image viewer, there is an object called the Viewport that represents a geometric model of the portion and scale of the image visible to the user.
a. Zooming and panning is a matter of changing the Viewport, then this change is broadcast to the visible components, including the view window, which will display a portion of the image at the appropriate scale. However the same broadcast also causes a change in the size and position of the little red rectangle over the thumbnail which shows the portion of the image being viewed. A single model object (the Viewport) has several controls which listen to change events and change their state when the model changes.
b. Clicking and dragging the mouse on the thumbnail causes the scroll position to change and pans the image by updating the Viewport. (It does not, by the way, change the red rectangle indicator directly, since that is driven by changes broadcast by the model.) Similarly the Viewport can be changed by clicking the zoom in or out buttons, or dragging the selection rectangle over a portion of the view window (in zoom mode) or dragging to pan the image in the view window. There are multiple ways to change the Viewport object! The nice thing is that if you pan by dragging on the thumbnail the image moves as you do it. If you pan or zoom using the view window, the thumbnail indicator moves and changes size.
2. Separation of Concerns
Every single line of code in Viewport is about the geometry of the view image and broadcasting changes. It is written with no knowledge of the thumbnail, the view window, data communications, or any other control. Instead it mainly deals with points, rectangles and affine transformation matrixes. This also yields a nice separation between the controls: the thumbnail navigates without worrying about loading image tiles, a TiledImageLayer worries about loading the images under the visible rectangle without worrying about the navigation, and so on.
All of this became confusing because web frameworks made "model" synonymous with objects corresponding to database records, where the business logic is often implemented. The Smalltalk vision of a simulation model interpreted by multiple views and modified by user controls is still the cleanest approach. Having model objects without behavior moves the implementation of behavior closer to the specifics of the user interface.
I am planning to start moving some of the image viewer and image annotation code into Infusion, and it would help a lot if I could have model objects with behavior and listeners. What is a good way to do that?
More information about the Infusion-users