3
\$\begingroup\$

This is a question I have in regards to my implementation of the MVC design paradigm that I came up with. The MVC type I am using is where everything must go through the controller. No communication happens between the model and the View. This is what I saw apple doing when I played with some iPhone stuff so I wanted to work through it, even though I had to put my iPhone stuff on hold.

So the issue I am having is I am seeing a lot of what I see as dirty, unnecessary looking code due to me trying to maintain this paradigm and because of this I have a feeling I am going about this quite incorrectly. So I thought I would seek some advice from you guys, who have much more experience in this sort of thing.

Here is an example of code that just gets handed from class to class just so that it passes through the controller:

I have a ViewController JFrame that holds all of the panels for my GUI. It also contains the next and previous buttons required for navigating through them.

So.. This is going to look scary but it is just a LOT of repeated code, I am going to put these in order of how they are called.

NextButton is pressed:

(ViewManager.java):

private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) { controller.nextPanelRequested(); } 

(Controller.java):

public void nextPanelRequested() { model.readPanel(); // Only following this chain ... } 

(Model.java):

public void readPanel() { ... //LOGIC TO DETERMINE WHICH PANEL WE ARE ON, WHICH DETERMINES WHICH 'FETCH' TO USE: case PANELX: controller.fetchPanelInfo(panelList[PANELX]); break; .... } 

(Controller.java [Again]):

public void fetchPanelInfo(Panel currentPanel) { ... else if (currentPanel.equals(Panel.PANELX)) { viewManager.getPANELXInfo(); } } 

(ViewManager.java [Again]):

public void getPANELXInfo() { // This calls down to a specific JPanel and gets it to collect input and send. panelX.collectAndSendPanelInfo(); } 

(PanelX.java):

public void collectAndSendPanelInfo() { viewManager.sendPanelXData(double1, double2, double3, ..., double 15); } 

(ViewManager.java [Again x2]):

public void sentPanelXData(double1 double1In, ..., double15 double 15In) { controller.sendPanelXData(double1In, ..., double15In); } 

(Controller.java [Again x2]):

public void sentPanelXData(double1 double1In, ..., double15 double 15In) { model.receivePanelXData(double1In, ..., double15In); } 

(Model.java [Again x2]):

public void receivePanelXData(double1 double1In, ..., double15 double 15In) { instanceVariable = new AppropriateObject(double1In, ..., double2In); } 

Okay... I hope I don't get too much flak for the length of this question, I rewrote everything to simplify it and hide my specific code.

I want you to see exactly what I am seeing, and this redundancy is what is making me uneasy.

*Sigh*. It works. The issue is that each panel has a different number, and different set of types of inputs, so I cannot simply make one method that could transport them all. So I have about 8 calls that appear in EVERY one of those 4 classes.

If there is some solution to my disgusting implementation of MVC I could delete around 30 methods and make future programmer's lives about 30x easier.. tracing through that line of code is terrible. And I CODED IT. :(

So Question: Should my model be asking the view directly for the panel info rather than going through the controller?

And: Should the model be transmitting its collected info in a better manner that goes directly to the model?

In the past I have seen a similar construct transmit the user input with beans, I was uncomfortable with this approach because they needed them for transmitting over a network, and I am just on one screen with one application.

All the handoffs I am doing here are not expensive.. They don't even factor in when I profile the performance of each method. I know the post is insane, but I would have killed for a post like this with an answer when I was programming this beast.

\$\endgroup\$
1
  • \$\begingroup\$If you are flexible, switch to Griffon. It handles the boilerplate of MVC for you and lets you just worry about the meat of the models, views, and controllers. While it's built in Groovy, it works just find for straight Java as well (much uglier, but that's just the nature of Java desktop development)\$\endgroup\$
    – cdeszaq
    CommentedJan 17, 2012 at 21:21

2 Answers 2

4
\$\begingroup\$

If you are sending everything through the controller, it's not exactly MVC.

The beauty of MVC is that most of your views "listen" to changes in the model, which means the controller doesn't need to "update" the views for regular data changes. That limits the controller's updating of views to cases where the view needs to be laid out again (such as changing screens, layout, etc).

Models that model changing elements (like clocks) don't even involve the controller. The model calls a (typically) private "changed(...)" method which signals all of the listening views. The views then fetch the data they are interested in (might be different depending on the view), and the view then invalidates itself (to schedule a redraw of itself).

One clock "view" might be a digital clock, another might be a changing non-editable text label, a third a "solar" representation of the sun / moon in different phases (dawn, morning, noon, etc).

Your solution could probably be fixed pretty easily. Initialize the views with a reference to their viewed model and cut out the controller "updating" the view for any data-related stuff. Normally the controller will still have to update the view for certain items, mostly for presentation (which view is visible, etc). Have the assignment of a model to a view cause the view to "unlisten" to the old model and "listen" to the new model. In the model, have any data change notify all the "listeners" of that model object's data change. The "listeners" then need to re-pull whatever data they might be interested in.

\$\endgroup\$
4
  • \$\begingroup\$Okay, I've cleaned up my code quite a significant bit by handing each of my Panels their own copy of the 1 model that exists. Now when they are called upon to collect & send their info they simply call model.receivedPanelXInfo(...) and that eliminated a lot of redundant hand-offs. I also made my controller implement ActionListener and now it handles next/previous button presses itself; which allowed me to keep a lot of control flow still emanating from the controller which I like.\$\endgroup\$
    – Alex
    CommentedJan 18, 2012 at 15:49
  • \$\begingroup\$One question I have - And I feel like the way I implemented this is still avoiding doing what you are suggesting - is when you say "listen" and "unlisten" for different classes.. How? With what methodology? Like I am doing; say a view calling a model's method? Or is their some higher intelligence implementation where you can actually set a model to listen to a view through some kind of set-up.. I know I've seen notify() kicking around the posts on this I read but I don't know if that works this way.\$\endgroup\$
    – Alex
    CommentedJan 18, 2012 at 15:52
  • 1
    \$\begingroup\$@Alex, Typically the view "knows" how to display a particular model, and the model knows nothing of how the information is displayed. The model "knows" which views are interested at any given time, and after the model changes, it "notify"s the each of the currently interested views that the model changed. Then each view queries the model(s) it is working with to determine if it needs to recalculate or change the display data, and if so, it schedules itself for being redrawn. In such a setup (which is only part of MVC) the model might call "notify" on the views to notify them of change.\$\endgroup\$CommentedJan 18, 2012 at 17:37
  • 1
    \$\begingroup\$@Alex, under a setup as described above, the controller is critical for building / maintaining the model (at initialization and as a side-effect of the input), displaying the appropriate view(s), and telling the views what models they are attached to. This means that if you have to "customer" model classes, and a few "views" that display certain aspects of a "customer", a button click to "go to the next customer" might be handled in the controller as simply as telling all the appropriate views that they have a new (different) customer "model": like nameAgeSexView.setModel(selectedCustomer).\$\endgroup\$CommentedJan 18, 2012 at 17:41
0
\$\begingroup\$

Regarding the implementation of MVC my co-workers and myself are against the view accessing to the model and should therefore always go through a controller. Still, if you feel it like having a direct link from view to model you're welcome to do it.

Regarding your 30 methods you should add another layer on top of these and use polymorphism. Create a abstract class where your panels will inherit from or you could implement an interface.

Hope this helped.

\$\endgroup\$
1
  • 2
    \$\begingroup\$MVC is not an opinion. It is a technique. Your technique might work well for you, but that hardly makes it MVC if the descriptions of the two techniques are not compatible. Your views don't listen to your model. You might have a good GUI framework, but because your views don't listen to your model, it isn't MVC.\$\endgroup\$CommentedJan 17, 2012 at 22:44

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.