CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Hybrid View

  1. #1
    Join Date
    Jan 2003
    Posts
    615

    MVC relationship

    What is good practice for the relationship between view and controller in the MVC pattern?
    It appears to me that this relationship can become quite strongly coupled and is this desirable?
    To discuss this issue here is a very generic example. Please ignore typos, which platform, graphical library to use and lack of using smart points etc.
    Say you have a view element that contains a textbox, a button with caption "add" and a listbox. So the user could type in "ABC" in the textbox and click "add" button and the string "ABC" would appear in the listbox.
    Here is a simple class definition for each of the classes;
    Code:
    class View
    {
      Textbox t;
      Button b;
      Listbox l;
    Private:
      Model *m_model;
    };
    
    class Controller
    {
    Private:
      Model *m_model;
    };
    
    class Model // observable
    {
    public:
      void add(const std::string& s);
      const std::vector<std::string>& getList();  
    };
    The view class should subscribe to changes in the model class using the observer pattern.

    In my opinion it makes sense for the controller to create and own an instance of the view class. So that would mean something like this;
    Code:
    class Controller
    {
    Private:
      View *m_view;
      Model *m_model;
    };
    An interesting description of a controller found online stated:
    The controllers are typically responsible for calling methods on the model that change the state of the model.
    So when a user clicks on the "add" button located in the view this action must be forwarded to the controller instance which will update the model. This can be handled at least two ways,
    a) The View contains a reference to the Controller which has a "add" method.
    b) The View is observable and the controller subscribes to its changes.

    This might not be a big deal but it appears that for each "operation" (i.e. button click) in the view, there might be a need for a matching method in the controller (maybe exaggeration a bit). So you might have multiple views with different operations but the controller must have a method for each operation. Can the controller class become bloated? Is there a generic way of solving this issue by reducing the coupling between View and Controller?
    Before post, make an effort yourself, try googling or search here.

    When posting, give a proper description of your problem, include code* and error messages.

    *All code should include code tags

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: MVC relationship

    Quote Originally Posted by laasunde View Post
    The view class should subscribe to changes in the model class using the observer pattern.
    I would advice against implementing the observer pattern yourself. It's not trivial to implement correctly, particularly to avoid dangling pointers. Instead, use a signal library (libsigc is lightweight, boost also has a signal library).
    Quote Originally Posted by laasunde View Post
    In my opinion it makes sense for the controller to create and own an instance of the view class.
    Not at all. You can have multiple views with a single controller. The application should create the model, controller and view(s).
    Quote Originally Posted by laasunde View Post
    So when a user clicks on the "add" button located in the view this action must be forwarded to the controller instance which will update the model. This can be handled at least two ways,
    a) The View contains a reference to the Controller which has a "add" method.
    b) The View is observable and the controller subscribes to its changes.
    This really depends on the GUI framework you are using. It could be that you simple bind a method to the button click event that takes the contents from the text box and calls a method of the controller. This could even be scripted. So, it is arguable whether the view is involved at all.
    However, the second option doesn't sound right to me, because the view should not hold any logical state. It may keep some internal state for efficiency reasons, but the application design should not depend on the state of the view.

    The advantage of MVC is that it becomes easy to guarantee that (1) your user interface always displays the correct state to the user (e.g. all items in the model are displayed on the list) and (2) your model is always updated correctly (e.g. to prevent double entries in the list). The first is done by making sure your view updates itself whenever the model changes. The second is done by taking care of all preconditions in the controller (or model).
    Quote Originally Posted by laasunde View Post
    This might not be a big deal but it appears that for each "operation" (i.e. button click) in the view, there might be a need for a matching method in the controller (maybe exaggeration a bit). So you might have multiple views with different operations but the controller must have a method for each operation. Can the controller class become bloated? Is there a generic way of solving this issue by reducing the coupling between View and Controller?
    This question is more about general design than MVC. If you start adding more code for each different piece of information in you program, then all classes will become bloated. To support larger applications, you'll find to find ways to abstract the interaction between model, view(s) and controller, such that the amount of code is not proportional to the amount of data the application handles.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Jan 2003
    Posts
    615

    Re: MVC relationship

    Quote Originally Posted by D_Drmmr View Post
    I would advice against implementing the observer pattern yourself. It's not trivial to implement correctly, particularly to avoid dangling pointers. Instead, use a signal library (libsigc is lightweight, boost also has a signal library).
    Agree. Boost is library of choice.

    Quote Originally Posted by D_Drmmr View Post
    Not at all. You can have multiple views with a single controller. The application should create the model, controller and view(s).
    Original post was poorly phrased on my part. What I meant was the controller should create all views (plural) and manage switching between views. Switching between views is a runtime decision and therefore in my opinion outside of the scope of the "application".

    Quote Originally Posted by D_Drmmr View Post
    This really depends on the GUI framework you are using. It could be that you simple bind a method to the button click event that takes the contents from the text box and calls a method of the controller. This could even be scripted. So, it is arguable whether the view is involved at all.
    Agree that binding a method to the button click event would work. This will require the button object to be accessible from outside the class. One way of doing this is defining the button object in the view as public but this reduces encapsulation. Another way would be to pass the Controller object as reference to either the View's constructor or Initalize method, and do the binding there. In the second solution you are adding detailed knowledge about the controller to the view.
    Last edited by laasunde; November 20th, 2012 at 03:10 AM.
    Before post, make an effort yourself, try googling or search here.

    When posting, give a proper description of your problem, include code* and error messages.

    *All code should include code tags

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: MVC relationship

    Quote Originally Posted by laasunde View Post
    Original post was poorly phrased on my part. What I meant was the controller should create all views (plural) and manage switching between views. Switching between views is a runtime decision and therefore in my opinion outside of the scope of the "application".
    Consider a situation where the user can make a selection from a list that controls in which way data is presented in the user interface (e.g. table of values vs a graph). You may decide that these different modes of presentation are best implemented in different view classes. When the selection in the list is changed, all that needs to be done is hide one view and display another (or create and destroy if you wish). I don't see the added value of involving a controller class for this.
    Quote Originally Posted by laasunde View Post
    Agree that binding a method to the button click event would work. This will require the button object to be accessible from outside the class. One way of doing this is defining the button object in the view as public but this reduces encapsulation. Another way would be to pass the Controller object as reference to either the View's constructor or Initalize method, and do the binding there. In the second solution you are adding detailed knowledge about the controller to the view.
    I don't see a problem with the view being dependent on the controller. All the diagrams in TheGreatCthulhu's post #3 also show this. The other way round seems problematic to me. There are typically more view classes than controller classes. If a controller class is dependent on multiple view classes, that is more difficult to manage than each view class being dependent on a single controller class.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    Join Date
    Jan 2010
    Posts
    1,133

    Re: MVC relationship

    I'd just like to add a few things to what D_Drmmr said.
    The architectural style you're talking about here is wrongly referred to throughout the web as MVC, when it's really Model-View-Presenter (MVP). There's an important difference between the two (see, for example, this short history of GUI architectures) and the traditional (per-widget) MVC is generally not used in applications today (although there's something called Web MVC now, but that's a different thing).

    When it comes to user interfaces, a distinction needs to be made between the (i) presentation logic and the (ii) application logic, where presentation logic defines the behavior of the UI (what controls are enabled when, under what conditions are certain elements of the UI shown, what color some ui element, like text, should have upon state change, and things like that), wheres application logic is what implements the business logic (what your application actually does, and the rules that govern it - what it's made for).

    Note that both (i) and (ii) can be rather complicated, and this is one of the main reasons why MVP is used - it facilitates unit testing, and the use of mock objects.

    Now, there are several variations of MVP depending on how (i) & (ii) are distributed among the View and the Presenter (your "Controller"), and the resulting dependencies between the Model, the View, and the Presenter.

    In Martin Fowler's terminology, there are:
    • Supervising Presenter - which he is not sure if he should call Supervising Presenter or Supervising Controller (adding to the confusion...).

      Here, the View handles user input (raw input) converting it into user gestures (like button clicks, and similar events), and forwards them to the Presenter, which then handles all further, more involved logic, updating the Model when required. In this design, it's interesting how the View-Model synchronization is solved: as much as possible is left to the View to handle, as long as the sync requirements are not too complicated, usually through some form of data binding - something these architectures often rely on. Only when something complex needs to be done does the Presenter step in to update the view (so it only handles complex presentation logic - which is what requires testing). Note the dependencies here: the View and the Presenter are relatively tightly coupled, and the View itself is dependent on the Model.
    • Passive View - this has been developed as an answer to some of the testability problems which arise from the way Model, View and Presenter are coupled in Supervising Presenter.
      Here, the View is made as thin and as "stupid" as possible.

      What happens here is that all the presentation logic and View-Model synchronization is moved into the Presenter, and the View is left capable of only the mundane everyday UI tasks (it knows how to paint a button depressed when clicked, and to raise events for user gestures - but that's about it). This way, there's no dependencies left between the View and the Model. Note that the View and the Presenter are still relatively tightly coupled. This is normal, and it can't be avoided - the reason is that you can't make some kind of a generic Presenter that would magically be suitable for any kind of View; rather, the Presenter is designed to work with a certain family of potential Views which are all similar in their fundamental properties and applications, although they might differ in a variety of ways (implementation, GUI libraries used, visual design, etc...). Note that here there are also opportunities for exploiting data binding and the Observer pattern.
    • Presentation Model - this variant eventually resulted in MVVM used in WPF developement for .NET (MVVM is Presentation Model tailor-made for WPF).
      Name:  MVVM.png
Views: 1036
Size:  84.4 KB
      This is another variation driven by the need to improve testability. Basically, the Presenter (or a part/component of it) is used to create an abstract model of the View (thus "presentation model"), in the sense that a representation of the View (or a View) is constructed in code (the same way you'd model anything else in code - using variables, functions, classes...), but without the actual UI (so the presentation model has a state variable which stores if a button is enabled or not, but it doesn't maintain a reference an actual button.) Then the presentation logic is implemented in the Presenter by modifying the presentation model. This leaves the View very thin. As all this state needs to be synchronized back to the View, this is used for those platforms which can facilitate such synchronization easily through data binding (or maybe which provide a way for the views to actually store their state in the pres. model), thus avoiding the need for a lot of boilerplate code. For example, this is perfect for WPF, and technologies that use XAML. It is usually said that View here simply represents a rendition of the presentation model (one of many possible renditions). The main ting here is that the View can now be completely left out from testing, because all the logic is moved into the presentation model, so now there's no more need for a test double or a mockup of the View.


    So, with all that in mind, let me also answer some of your questions:
    Quote Originally Posted by laasunde
    This might not be a big deal but it appears that for each "operation" (i.e. button click) in the view, there might be a need for a matching method in the controller (maybe exaggeration a bit). So you might have multiple views with different operations but the controller must have a method for each operation. Can the controller class become bloated? Is there a generic way of solving this issue by reducing the coupling between View and Controller?
    As you can see, by the nature of things, there will always be some amount of coupling between the View and the Controller (Presenter). Assuming that the View forwards all user gestures to the Presenter (where user gestures are messages/events like clicks and such, converted by the View from raw user input), the Presenter must provide a way to handle them - but of course, you can solve this in more than one way, and can design your application in a way that minimizes code bloat. For example, a Presenter for a View with 15 radio buttons would not necessarily require 15 different click handlers; depending on the application, it's probably possible to communicate the currently selected option to the presenter by passing an object that represents this state to a single function.

    Quote Originally Posted by laasunde
    So when a user clicks on the "add" button located in the view this action must be forwarded to the controller instance which will update the model. This can be handled at least two ways,
    a) The View contains a reference to the Controller which has a "add" method.
    b) The View is observable and the controller subscribes to its changes.
    A comment to what D_Drmmr said: In UI frameworks which provide events (like Windows Forms in .NET), (b) is exactly what's happening - under the hood, a click is detected by the control, and then a click event is raised, which results in calls to subscribed handlers. Note however that there's no difference in the direction of the dependency here; for (a) View references the Controller, and in the Observer pattern (b), the observable object (View) accepts subscribers (here just the Controller) and maintains a reference to them, so that it can notify them of changes. The difference is that with the Observer pattern there is a level of indirection, introduced by the fact that the subscribers (observers) are all referenced through the Observer interface which all of them implement - which means that the types of concrete, derived observes remain unknown to the subject [of observation].

    So, an important thing to note is that most of these architectures rely on some kind of data binding or signal library to ease the development process.
    Last edited by TheGreatCthulhu; November 15th, 2012 at 11:57 PM.

  6. #6
    Join Date
    May 2009
    Posts
    2,413

    Re: MVC relationship

    ---
    Last edited by nuzzle; November 16th, 2012 at 11:56 PM. Reason: doubleposting by mistake

  7. #7
    Join Date
    May 2009
    Posts
    2,413

    Re: MVC relationship

    Quote Originally Posted by laasunde View Post
    Is there a generic way of solving this issue by reducing the coupling between View and Controller?
    Yes there is and that's to make all participating entities to be interfaces, or pure virtual in C++.

    MVC and variations of MVC are often explained in terms of several other standard design patterns such as Observer, Composite and Strategy. What they all have in common and what they share with most other design patterns regardless of what they're for, is that the actual decoupling is achieved by the way of interface.

  8. #8
    Join Date
    Jan 2010
    Posts
    1,133

    Re: MVC relationship

    Thanks for pointing that out. So to relate this to my own post: while, on one hand, you can't create a universal, solution-for-all-problems Controller (Presenter), since there are certain high level structural requirements when it comes to the UI, requirements that affect the design of the Controller (Presenter), on the other hand you can increase decoupling by introducing a level of indirection; this way you can provide (and with the introduction of composition, dynamically switch between) several different behaviors for your UI; that is - you can customize presentation logic (and even application/business logic) by subclassing.

    In short:
    high level structure <-------- (relatively fixed) ----------------- (relatively flexible) ---------> behaviors
    Last edited by TheGreatCthulhu; November 18th, 2012 at 03:10 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured