Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

May I Merge MVC's View and Controller?  RSS feed

 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Still learning about MVC. I've read several tutorials and, lo!, there is some disagreement out there about how to implement MVC patterns. I can live with that, so long as I understand what I'm doing and why.

I've written a couple of simple MVC projects that work fine, but I am noticing that my controller methods all tend to be one-liners that mimic the view code that calls them. For example, if I have a button that, when clicked, should cause the model to change state, my view code calls a controller method something like this:

with the controller's corresponding method looking something like this:

Now, it seems pretty widely agreed that the view code isn't supposed to change the model's state. It can query the model for its state, but only the controller should be allowed to change it. By giving the view a reference to a controller (a use of the Strategy pattern), the idea seems to be that what the controller does in response to user input can be altered, without the view code having to change.

That's all very nice, but is it worth the extra level of indirection created by the controller when the controller's methods are all (or almost all) the kind of one-line "pass through" methods I'm encountering (like the above). It seems to be little more than false submission to the rule that the view doesn't change the model's state when, on a one-to-one basis, the view simply tells the controller to tell the model to change the model's state.

I've read, here and there, that the isolation of the controller from the view made much more sense when the MVC pattern first appeared, back in the '80s, because it had the responsibility of reacting directly to mouse and keyboard input. In Java, when using Swing, the Swing GUI components have their own MVC implementations, with the result being that the GUI has responsibility for handing mouse and keyboard input. In my code, therefore, I have the view reacting to input, and reacting by calling the controller. I'm wondering if that's now an artifact of a bygone era, since the view code has already done what an early (Smalltalk-80?) controller would have had to do.

Thinking further along those lines, would it make sense to have a GUI-based controller, with buttons and textboxes and all that, which was implemented in a class of its own, and a display-only view, with no controls that reacted to user input?

To boil it down, I'm asking these questions:

1. Is it a practical option to combined the view and controller functions in an MVC application?
2. Is it a practical option to include GUI controls in the controller, while leaving display of the model's state to the view?
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If anyone wasn't already bored into unconsciousness by my original post above, here's a simple MVC Java project I created to exemplify my concern. When run, it shows this:



Clicking on the button calls its action listener, which calls the controller's flip method, which calls the model's flip method, which changes the model's state and tells the model's registered view that the model has been updated (in a real-world program, the model, or a supporting class, would keep a list of registered views, but I excused myself from that complication for the sake of keeping this example simple). The update code in the view queries the model for its state, and sets the selected state of the checkbox to match.

Here's the startup code:



The model:



The view interface, as seen by the model:



The implementation of the view interface in a concrete view class:



And the controller:



This is about the smallest MVC Swing application I could write, but even the bigger things I've been doing/working on often show the same structure, where a call to a controller method from the view results in a virtually identical call to a model method from the controller, leaving me wondering if the controller is doing anything more than fulfilling the commandment that the view shalt not modify the model's state.
 
Campbell Ritchie
Sheriff
Posts: 55329
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sounds like what we usually discuss in the Swing forum, so I shall move you there.
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, you could clean up the view by making the controller responsible for event handling. A controller could potentially also serve more than one view.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Sounds like what we usually discuss in the Swing forum, so I shall move you there.

Thanks. Wasn't sure where this should start, myself.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle Klap wrote:Well, you could clean up the view by making the controller responsible for event handling.

How would I go about doing that? Unless the controller includes the button as a member (which is what my Question 2 is about), how would it react to user-input events?
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
Jelle Klap wrote:Well, you could clean up the view by making the controller responsible for event handling.

How would I go about doing that? Unless the controller includes the button as a member (which is what my Question 2 is about), how would it react to user-input events?


By having a controller implement the appropriate interface or extend an adapter, and adding it as a listener of view component. You could use action commands to differentiate between components and views.
The controller would also be a useful place to put the logic needed to execute operations asynchonously on the EDT.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle Klap wrote:
Stevens Miller wrote:
Jelle Klap wrote:Well, you could clean up the view by making the controller responsible for event handling.

How would I go about doing that?

By having a controller implement the appropriate interface or extend an adapter, and adding it as a listener of view component.

I'm a bit confused by what you mean. Aren't I already adding the controller as a listener of the view at lines 31-34 of ConcreteView?
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In your example have Controller implement ActionListener and in you buildGUI() method add the controller instance as an action listener to the button: button.addActionListener(controller); - note that the buildGUI(); invocation in the ConcreteView constructor should take place after setting the controller.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle Klap wrote:In your example have Controller implement ActionListener and in you buildGUI() method add the controller instance as an action listener to the button: button.addActionListener(controller); - note that the buildGUI(); invocation in the ConcreteView constructor should take place after setting the controller.


I get you. Now, that would work fine for my one-button example, but what happens when there are many buttons? If each adds the same controller as its ActionListener, there's going to have to be a big switch statement in the controller's actionPerformed method.

However, one could add something like this to the view code:



then add this to the controller:



I'm not wild about this (though Westchester University likes it), because it requires the controller to create (or receive a reference to) the view, whereas I'm (presently) in the community that sees the controller as something you pass to the view. Also, neither of these approaches makes much difference to my central concern: what's the point of separating the controller from the view, if user-input events are initially processed by view code?
 
Rob Camick
Ranch Hand
Posts: 2787
12
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
May I Merge MVC's View and Controller?


This is the way all Swing components are implemented.

Check out the 5th paragraph in How to Use Models.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Camick wrote:Check out the 5th paragraph in How to Use Models.

Slam-dunk!
Thanks, Rob.

Any other thoughts?
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
Jelle Klap wrote:In your example have Controller implement ActionListener and in you buildGUI() method add the controller instance as an action listener to the button: button.addActionListener(controller); - note that the buildGUI(); invocation in the ConcreteView constructor should take place after setting the controller.


I get you. Now, that would work fine for my one-button example, but what happens when there are many buttons? If each adds the same controller as its ActionListener, there's going to have to be a big switch statement in the controller's actionPerformed method.


That is definitely a risk, but one that can be mitigated by thinking carefully about the granularity of views. It could make sense to split a large view into several smaller views consisting of logical groupings of a few components in a sub-panel. The accompanying controller probably wouldn't have to be such a monstrousity. Honestly, it has been a really long time since I made anything non-trivial with Swing. Actually I was still in college at the time and I was tasked with designing and implementing a photo album application using various architectural and design patterns; MVC being one of them. I do remember clearly struggling with how to approach an MVC implementation in Swing, going with action commands initially and ending up ditching that approach and going a different way. Don't remeber the details though, but I know I did preserve the separation between view and controller. I've been trying to locate a backup of that old project, but I haven't found it yet
I know the Swing designers decided to merge view and controller for components, because the strict seperation just didn't make sense at that level of granularity. I think that the controller / view seperation can make sense for higher level views, though.


Also, neither of these approaches makes much difference to my central concern: what's the point of separating the controller from the view, if user-input events are initially processed by view code?

I thought of the controller as a good place to stuff the event handling code, because it cluttered up the view with anonymous or nested classes, though as of Java 8 that is somewhat less of a problem. Also, low-level input events are handled, but things like responding to button combinations aren't. You need to implement that as part of the event handling code, which would clutter up the view even more. I also found the controller a nice place to put the boiler plate code necessary to execute task asynchronously on the EDT. Looking back at the application I made in college, we als had to implement the Command pattern and I believe that tied in to my controller implementations also. I really have to find that backup.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle Klap wrote:I really have to find that backup.

Love to see it, if you do.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!