2

This is something that has been bugging me for a bit in a program I am trying to build. It is a desktop GUI application, and I settled on the use of the famous "MVC" (Model-View-Controller) architectural pattern for separating out the GUI and business logic. I've spent many hours wracking my head over various descriptions of this pattern that all seem to either not directly address the desktop use case, or contain a lot of jargon with regard I am not familiar, e.g. this:

https://stackoverflow.com/questions/5863870/how-should-a-model-be-structured-in-mvc/5864000#5864000

was perhaps one of the most interesting articles I found on the topic, but it took me many hours to penetrate because it was written for someone programming PHP in a Web context, which is not my chief area of programming experience. That said, I think I finally understand all the structure of the MVC pattern and could easily give a similar writeup with much less jargon.

However, the devil is in the details, and that's where I'm hung up right now. In particular, I am interested in the relationship between the View and Controller components - most questions on this seem to talk of the relation between the View/Controller and Model, but here it's this relation that's bugging me because as I understand it, Controller objects should not know about View objects and conversely, except in a very abstract sense which basically amounts to them passing messages or events between each other, particularly when seen in light of other design principles like SOLID (esp. the "I"). For example, a Controller object should not know there are things called "Views" out there, but it might know that there is a thing called a NewTweetsReceiver. This tiny interface would, of course, be implemented by a View or perhaps several Views, c.f. Observer pattern.

All this is good so far - but now consider this. It is very common that we have in a desktop application the dynamic creation and destruction of GUI elements. For example (and this is actually where I am at!) when you hit the "New" command in a document editor, the next thing to happen may be that the editor throws a dialog box at the user asking for various initialization parameters for the new document to be created. The question is, though, where should we place the creation of that dialog box? What has the responsibility for that? Because I've heard statements like that "Controllers return Views" which suggests to me the following "back and forth" process:

  1. The user clicks on the "New" button in the application main window (which may be a view or several views in code).
  2. The view that has control over that "New" button tells a controller that the user wants to create a new document.
  3. The controller now produces as a response to that a view which is the dialog box (or could be, at least) asking for information.
  4. The user puts this information into the box and hits the "OK" button. In code, the view now informs the controller of the information entered.

But then it seems that when you do that, the neat walls of separate responsibilities start to erode, as we've effectively mixed together specifics of how the UI is laid out, namely, that it's apportioned between a main window and a dialog box, into the controllers, because the sequencing of events implied and even the creation of that dialog box are now baked into the controller logic. And that doesn't seem kosher: if we decide to change that organization, we have to invade the controller, which we shouldn't have to do so long as we're not adding new functionality, just reorganizing the UI.

So, how should we lay this out to properly preserve the V/C separation in the MVC pattern? The only alternative I can think of is having the main window part spawn the dialog directly, and the Controller only ever knows of a "create new document" as "create a document with such-and-such parameters", completely oblivious to however that stuff is gathered from the user. But if we take the dialog and window to be Views, then is it kosher to have views create each other? Yet I've never heard of that in any material I've found on this topic.

What am I missing here?

3

No. Controllers are very well aware of views, directly or indirectly via abstractions such as factories.

That being said they shouldn't be aware of the implementation, just the role that they play, this is often an abstract base class, interface, or some expected duck type depend on the specific language. So in your example...

  • The Controller isn't aware of the view the user interacted with to activate it. It could have been a menu item, a button on a ribbon, a key command (ctrl+n), or an automated macro command from a running script.
  • The Controller is aware that it needs to present a request for more information. That request is the presentation of a view. However it shouldn't get hung up on that being strictly graphical, after all that macro command might be headless (no windows), or you might be porting this for blind users who need an audio equivalent. So the implementation will vary but the purpose, a view to extract information, does not and the controller must be aware of it.

A good way to handle this is for the view to also pass in a ViewFactory when calling controllers, or for the controllers to be created with a ViewFactory before being attached to a view. Eitherway its the same effect, when the controller needs a view it asks the ViewFactory for a view that achieves X.

So strictly speaking controllers do not create views, but they are responsible for determining which view and when to create it.

That being said Controllers don't micro manage views, the view is responsible for reacting to how the model changes, and Controllers manage models. If the view has properties that the model does not (such as being visible, enabled, etc...) the solution is to create a ViewModel (often it composes the model, or extends of the model, but not always). The controller updates the ViewModel, and the View responds to that as well.

The first view though is created by the application startup itself.

17
  • Thanks. So basically it knows what kinds of views exist in the program (as opposed to that being handled by some outside facility), but it doesn't know how they are implemented. I have one more question, then: in light of the "SOLID" principles, how do you deal with the "D" part, the "dependency inversion principle", i.e. which one "owns" the abstraction of the other, given that View and Controller seem to relate cyclically to each other in that View has to at least send events to the Controller as well? – The_Sympathizer Nov 30 '20 at 4:57
  • Depends on how you architect it. Do you have a real event loop inside your domain? The view might simply send their events there. The controllers being registered to listen for events from that loop. However I tend to find that the event loop is the one supplied by the graphical environment of the day in which case the views are the registration mechanism. In this case a View is aware of callbacks (which are function entry points into controllers), the factory responsible for their creation would also be responsible for creating controllers and registering their functions, or for... 1/2 – Kain0_0 Nov 30 '20 at 5:49
  • ... creating another inline factory that creates the controller on the fly and passing the information along. 2/2 – Kain0_0 Nov 30 '20 at 5:49
  • @The_Sympathizer One way to understand MVC is that the basic idea (from which there are various degrees of deviation in practice) is that the view is "stupid" in the sense that it doesn't understand what it's doing in terms of business logic. E.g., it just knows a certain button on it was clicked, but doesn't know what it's for. The controller knows what it does (but not how) - it knows what logic to call to make it happen, it knows what to do with the response, and what else should happen in the view (e.g., what should be updated, or disabled - what we call presentation logic) 1/2 – Filip Milovanović Nov 30 '20 at 6:44
  • This view/controller communication is often done through an abstraction of some sort, such as a databound ViewModel (lets you do things like have multiple views of the same thing, or freely fiddle with view design, or test nontrivial presentation logic in an abstract way, without instantiating a view). The different variations of the pattern are essentially about how smart or stupid the view is, and about how you divide responsibilities within the controller. 2/2 – Filip Milovanović Nov 30 '20 at 6:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.