Assignment #2: Solution

This is a sample assignment solution, not the only possible solution set to the questions. Your answers and code might differ from these. This solution is being given as a study guide.

Q1: TempController and TempModel

This part of the assignment was not tricky, but it understanding composition (has-a), inheritance (is-a), and delegation was crucial. Any trickiness resided primarily in the trickiness of these concepts. A secondary issue is the coupling of objects.

The question issue was the fact that TempController was itself tightly coupled to TempModel since

  1. it knew that it was changing a TempModel
  2. it knew it should change the model through setTemperature(), and
  3. it knew that it was to randomize the setting.
All these things could be decoupled from TempController so that it was not as dependent upon TempModel. In other words, if either of your assignment solutions had these dependencies, you would lose marks.

There was two main ways of increasing the separation of TempModel and TempController: through inheritance and through delegation.

(a) Inheritance
In the inheritance method, a subclass of TempController was created and it was to know which TempModel to change and how to change it. A sample solution is here. (Note the second hint (inner class) was used but not needed.)

(b) Delegation
Delegation is accomplished by making use of a delegate object. Remember the controller is supposed to respond to external (i.e. interface) events by sending off an event to the model it is controlling---or to another object that can handle the event. That is, the TempController, being a controller, should delegate another object to respond to the interface events, and furthermore, this object should be passed in to the TempController. An example is located here.

Why must the delegate be passed in? In the original, the delegate object is created by TempController in a new ActionListener() expression. In the new code, this is done by someone else who knows what the delegate object should do, not TempController. The whole point was to have another class make the delegate that knows what model to control and how. If TempController made the delegate, no separation was being accomplished.

Note that the sample code used might be considered a kind of a "cheat" since it lets the AWT component do the delegate collection and firing. Why might it be considered a cheat? Mainly it is because the delegate object might not want to know how to "speak AWT". The point of separating out the model in MVC is to ensure that the model code does not need to know UI code. So perhaps your delegate object does not want to know about java.awt.event.ActionListeners, for example, in case it wants to be connected to a different UI toolkit. Of course, in Java, it is unlikely that someone would not use AWT since it is supposed to be the universal toolkit (the abstract toolkit). However this is not necessarily so, and is certainly not true in other programming languages you might encounter, so I wanted to make this point in this sample solution. This will be brought up in question #2.

Comparison:
One can make many different arguments about the two implementations, but arguing to hard for either of them usually amounts to dogmatism. The main advantage to the delegation method is the runtime flexibility: multiple listeners can be specified at runtime (an addActionListener() would need to be in the tempController() interface, of course). The connections between controller and the things it controls need not be specified until runtime. This is probably the best answer to this question.

The delegation method also has a secondary advantage. The subclassing method requires knowledge of a non-standard protocol (doAction() as an analogue to event-firing) rather than a standard naming such as AWT's event naming system (xxxEvent/xxxListener, etc.) or the Observable/Observer standard naming for delegation.

(c) ThermometerMVC318 achieves better separation.
First of all, UI code is well separated from application code in both: the model has absolutely no UI code in it, and the same TempModel is used for both. However that does not mean the reverse is true: the application code is not equally separated from the UI.

There are two telling lines in ThermometerMVC1:

  1. tempController.addObserver ( tempView ) in ThermometerMVC1.init()
  2. tempModel = new TemperatureModel() in TemperatureController1.TemperatureController1().

This first tells us that Controller and Model are not correctly separated (that is, application code is not correctly separated from UI code). Why is a View listening to events from a Controller? The Controller should be controlling a Model. Clearly, the Controller knows too much about the application code. What if you wanted several controllers on the model? You'd have to call TempController.getModel() to find out model to control. This is not only a flaw in the MVC separation, it fails to properly separate application code from model code.

The second line demonstrates that the controller is dependent upon the model class since it constructs the model in addition to updating it directly.

ThermometerMVC318 fixes these problems by moving the TempModel construction out from the controller. The changes to part (a) and (b) merely clean up the MVC architecture, but do not fundamentally add any separation between interface code and application code.

Q2: Browser Applet

The sample solution is quite self-explanatory. It contains 5 main objects and 4 connector objects to hook up those 5 main objects. It also has 2 additional internal event adapter objects.

See the javadoc for a formatted description.

Note #1: in the above I mentioned that one might wish to erect a barrier between UI code and non-UI code so that the MVC components communicate without using UI code (such as java.awt.Event objects). The example solution uses the Observer class to accomplish this. This is likely overkill and unnecessary but I wanted to give you an idea of how this could be accomplished. It is left as an exercise to the reader to remove the adapter classes and have the model updated by a delegate object responding to AWT events directly instead of an AWT-event to Observer-event adapter.

Note #2: The solution separates the two types of controllers. This is the preferred solution for this assignment, where the objective was to apply the MVC concept to the program solution. As mentioned in all the MVC references, the purpose of the MVC architecture is to allow and promote multiple separate controllers (and views). If your solution merged both controller actions into a single controller, look over this solution. You may not have lost marks if you made this solution, but unless you gave a good reason for merging the controllers together, you probably should have.

Updated: Feb 14, 1998