The model-view-controller paradigm dominates the UI toolkit world. I should say, it dominates the talk about the UI toolkit world.
Most UI toolkits have very poor separation between the model, the view, and the controller. For most UI toolkits, a text input field can only have one controller and one view. Further, all of the aspects of the controller, the view, and the model are accessed through the text input field object.
I tried to google around for “model view controller” alternatives
and “model view controller” rethinking
. The only alternative that I saw was DDP (data driven presentation). Data driven presentation seems like someone took the model-view-controller paradigm and collapsed the view state into the model. This makes for a somewhat nicer entity-relationship diagram because then the controller never has to speak directly to the view, it can just twiddle the data
.
I don’t think data driven presentation is a real alternative to model-view-controller. It is a slight repackaging of something that’s never been packaged right before, to my knowledge.
I don’t really like the model-view-controller paradigm very much. I would love to hear about alternative approaches to representing the same control in multiple places in an application. Alas, in the absence of an alternative, I have been trying to think about how to do model-view-controller right.
Let’s try a checkbox
What is the model for a checkbox? At its simplest, a checkbox is either checked or not. It is a simple boolean value. The checkbox doesn’t exist in a vacuum though. It probably needs a list of listeners that want to be notified when the checkbox is toggled. So, the checkbox model is two things: a simple state and an initiator of state-change events.
Does the model have a label? I say, No.
If the model had a label, then I cannot display it in two different places with two different labels. If it is going to have any sort of label at all in the model, it should merely be a label indicator. Let’s imagine that I am making an interface that is English on the left side of the dialog box and Spanish on the right side. If I am truly separating model from view, then I should be able to use the same checkbox model on both halves of the screen. I cannot keep the text label in the model unless one of my views knows how to translate. If one of my views is going to know how to translate, then both of them should. Me, I don’t think that either should.
What is the view for a checkbox? A checkbox view at its simplest is just an indicator showing whether the box is checked or not. It might be a rendering of the box on your screen either empty or containing a checked mark of some sort. It might be a rendering of the box on a remote screen. It might be the little Caps Lock
light on your keyboard. It might be a green table cell on a web page.
Does the view have a label? I don’t know. It makes more sense here than in the model, but does it belong here? Suppose there is some event elsewhere that makes me want to change the label. Suppose my label was include all images
. Then, suppose someone adds a sound file into the document, and I want to change the label to include all images and sounds
. I have to track down all of the views and update them. I would still have to do this if the label were a separate entity apart from the checkbox. So, the question is, should it be a separate entity?
What is the controller for a checkbox? For a checkbox rendered to the screen, the controller has to recognize mouse clicks in the same area that the view is in. Either the controller has to moved around lock-step with the view so that it has the same geometry, or the controller has to know enough about the view to tell whether a mouse event hit it. Similarly, if the checkbox has focus, pressing the space bar or the enter key should probably toggle the checkbox. The view has to know if it has focus so that it can render itself to appear focused. The controller has to know if it has focus to know whether to care about the key press.
It is tempting to combine the controller into the view. It definitely simplifies the geometry and focus questions. Those become shared information. There are other possible controllers for the checkbox, too, though. Maybe the checkbox has a global hot-key. Maybe there is some menu item that uses the same checkbox model (though a good menu item will also act as a view of the checkbox model, so it really is a combination view and controller again).
Is enabled
a property of the model or the view or the controller? I say, not the model
. Of course, this is thorny. Suppose that my checkbox isn’t relevant at this point in my application. I should disable it. However, I have to update all of the views attached to this model instead of just updating the model. Feh. Of course, I also have the option of disabling just some of the views. For example, if my application supported multiple users watching, but only a single one editing, then I would need to disable this checkbox in every window except the one on the editor’s desktop.
Is focus
a property of the model or the view or the controller? It shouldn’t be part of the model. If I am displaying the same model to two different desktops, there is no reason that the two users should have to synchronize which control they are using. Heck, what’s to say that the second user even has all of the controls that the first user has?
Where we are
The controller and view definitely need to know about the model. The controller and view both need to know about focus
. The controller and view both need to know about enabled
. The model needs to be able to tell all of its views that they are stale. For items that are going to be taking mouse input, the controller definitely has to know where the view is being rendered.
The fact that the controller and view both need to share the focus
and enabled
information (as well as caret position
and selection range
and such for other types of controls) indicates that there should be another entity in this paradigm that both the controller and view can refer to. There is both a model of the item and a model of how that item is to be presented—a model and a presentation model, if you will. If there are two users sharing the same text input field, then the GUI should have the choice of sharing the presentation model across users so that they both have the same caret position
and selection range
or allowing them each their own presentation model so that they each have their own caret position
and selection range
. It is further complicated by the fact that you may want to share the caret position
and selection range
without sharing the focus
or enabled
settings.
I am afraid that I haven’t reached much conclusion here. I still don’t have answers or alternatives. Any references or suggestions would be greatly appreciated.
I think it might be helpful to refine what you’re considering as the controller. In this consideration of alternatives, you mostly have the controller combined with the interface. Reading others’ descriptions of MVC, I see this frequently, but I think this is a mistake and a misrepresentation of the original intent of MVC (and perhaps the confusion arose from some of the vagueness in the naming convention, but that’s an anthropological investigation for someone who cares about it more than I do). Anyway, this is how I see it, and I think this manner of segregation could clear up some confusion, though, even as described here it may not overcome some of the inherent complications of MVC.
Model: Concerned with storage of data (used by controller to get data and to persist changes).
View: Concerned with presentation of data (and provides and optional conduit for requests to the controller).
Controller: Concerned with what can be done with the data — the heart of the application. The model is just house keeping and the view is just window dressing.
So the model gets data from its store where it is perhaps a boolean expressed as a character “Y” or “N”. The controller represents it internally, and indeed to the rest of the application as an actual boolean value, as it should. And the view may present it to the user as “Oui or Non”, “Enabled or Disabled”, “On or Off”, or whatever.
The Controller is calling all the shots. The model does the controller’s bidding, and the view(s) need to kowtow to the controller to get anything done for the user. The controller is where the event dispatchers need to live; it will be getting incoming events from views and if permitted, issuing events on to the Model layer for persistence while notifying any other existing views of data changes that it has allowed. In your examples, where one user is allowed to edit and multiple users can view, a sensible implementation of this requirement would require the view to request edit permission from the controller before it lets the user perform editing operations.
Interaction between the View and Controller layers is unavoidable, and while the Controller is the one calling the shots, deciding whether it is permissible, for instance, to change a given value under the current circumstances, the lines between view and controller will, at least in terms of their physical locations, become blurred by necessity. Are you going to issue a network request for each item in a user interface to interact with controller logic back on a server? No. Minimally rudimentary, or even rather sophisticated, parts of the controller are going to be pushed from the server layer up into the client presentation layer to make the interface more natural and responsive. But this does not make them part of the view, they just become part of a distributed controller. If implemented properly, the controller portion that is resident in the client presentation layer will not know whether the user selected “Oui”, “Enable”, or “Hell Yes!”. It will simply know that someone’s trying to set something to true, and it will decide of its own accord whether or not this action is permissible.
Anyway, when you get down to it, the view needs to know about the controller, of course, but controller needs to know about the model while the view does not. The view’s interaction with the model is mediated through the “neutral” territory that is the controller.
Is it easy to make this simple and elegant? Current technologies would tend to suggest: No. If you do find a framework that does manage this with simplicity and elegance, do let me know.
I responded a little bit last night from my phone, but somehow managed to not get it to take. Hrrm.
First off, thank you for the lengthy, insightful response, Jim. I have seen the sort of division-of-labors you are mentioning in Web applications. Typically the model portion is some opaque ORM layer. With desktop UI toolkits though, I’ve never seen such nice division.
Actually, I’m not sure that I think it’s all that nice. I think it emasculates the model, if I’m understanding you. When the checkbox above goes to render, it needs to know if the box is checked or not. Are you saying it queries the controller to discover this? I can see it querying the controller to see its focus state or its enabled/disabled state and even, to some extent, its visible state. But, its checked or unchecked goes through a broker?
As far as bad examples from the real world go, the javax.swing.ButtonModel seems to be a controller. It has methods like:
boolean isEnabled();
boolean isRollover();
boolean isSelected();
void setActionCommand( String _cmd );
void setIsPressed( boolean _is );
Of course, you have to dig pretty far into the class hierarchy of JCheckBox to find the
at all. It is mostly wrapped up in an opaque way where you couldn’t add a second view to a button.Qt doesn’t seem to even try to separate out the pieces.
*shrug*
[…] not fond of MVC and yet I know of nothing better. What would I want in an […]