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\$

migrated from stackoverflow.com Jan 17 '12 at 21:58

This question came from our site for professional and enthusiast programmers.

  • \$\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 Jan 17 '12 at 21:21
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\$
  • \$\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 Jan 18 '12 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 Jan 18 '12 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\$ – Edwin Buck Jan 18 '12 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\$ – Edwin Buck Jan 18 '12 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\$
  • 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\$ – Edwin Buck Jan 17 '12 at 22:44

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.