Skip to main content
GameDev.net gamedev.net
🔒 Locked

model view controller?

Started by FxMazter Feb 21, 2006 at 11:36 AM 6 replies 1.3k views
Original Post
FxMazter
FxMazter
Hi everyone! I'm trying to grasp the concept of Model-View-Controller. I would say that theoretically I know how everything should work. But when it comes to implementing the stuff, I'm little confused... it seems to me like the concept breaks. For example, lets say I have an application that has a Phonebook displayed on screen and a button to add new data to the phonebook. Ok, so I have the classes like this:


//This is the model class
class Phonebook {...}

//This is the view
class PhonebookGUI {...}

//This is the controller
class PhonebookController{...}


The PhonebookControlleris initialized with both a Phonebook and a PhonebookGUI:

PhoneBookController myDefaultController = new PhoneBookController(phonebook, phonebookGui);
Then the PhoneBookController registers itself at the PhonebookGUI to catch all events, and then when an event from the PhonebookGUI arrives it is handled like this:


PhonebookController::actionPerformed(Event e)
{

  //Now we need to determine what even was fired:
  if(e.getSource() == phoneBookView.addButton)
  {
    //We now control what should happen when the add button is pressed
  }

}


But as I see it the PhoneBookController is now BOUND to the specific VIEW. So now for instance, I could not change the PhonebookGUI from a visual gui with the "addButton" to a console view which uses the input from console as actions. So, it's kind of pointless separating the View and controller in this case?? What I can think of instead, would be to have the controller implement an interface like this:


interface PhonebookGUIListener
{
  public void onGUIAddPhonebookEntryEvent(...);
}

Now I could have the PhonebookController implement this PhonebookGUIListener interface, and register itself by the PhonebookGUI. So, I could now implement a Console version of PhonebookGUI and be asured that the application would still work correctly even though I switched the interface. But on the other hand, the PhonebookController is no longer a controller in the same sence as the Model-View-Controller intended it to be?? Also, now the PhonebookGUI will need to handle some of the GUI events on its own, which is initially intended to be handled by the Controller? Any comments on this would be appreciated! Now my question is the following. How would I handle the events in the PhonebookController, whithout having it BOUND to a specific VIEW?? For example, I would want to be able to switch from a Windowed view to a console view... whithout having to replace the entire PhonebookController as well. Thx !
ApochPiQ
ApochPiQ
The Controller component is not generic in MVC. Controllers and views are, by necessity, tightly coupled. Here's a quick recap of the theory:

Model - The data (names and phone numbers) along with operations you can do on that data (look up someone's phone number given their name, etc.). There is one Model for each chunk of data (i.e. one Model object per phone book).

View - Code that displays the data to the user. There is one view per interface that displays the data.

Controller - Code that lets the user tweak the view, and maybe also the data. There is one controller per View, and in many cases they are bundled together into the same class or class structure.


So in your case, you'd have a GUIView and a GUIController. The GUIController would take care of handling all the ugly bits of button clicking, etc. Similarly, you'd have a ConsoleView and a ConsoleController, with the ConsoleController taking care of reading input from the console, and the ConsoleView writing stuff back out.

The key separation here is "[Model] vs [View and Controller]" rather than "[Model] vs [View] vs [Controller]." Of course, depending on your preferences and needs, it may be useful to have a single interface that all views and controllers share - but then again, it may not.
acid2
acid2
I understand this differently to ApochPiQ, and I expect I'm wrong. I have only used the MVC pattern in ruby on rails because that is the way your code with it. My understanding is that the model is like a class in OO programming - its meant to represent some type of object. So in your case, you have a PhonebookEntry model, which has the properties of things like phone number, name and so on. The controller is then something that has different actions, that is - things to do. The actions if they have a view, fetch the required models for the view, and then call the view to present everything. The view is just a frontend, it just uses whatever the controller gives it, presents it, and calls back to the controller, usually via a different action.
ApochPiQ
ApochPiQ
There's a few different views on MVC. Mine is pulled from the literature and people who I like best, and specifically from Pragmatic Programmer's description. I used MVC-style patterns long before Pragmatic Programmer came into my life, though, and they were basically always in the same vein. I prefer mine because, in practice, it seems to work out cleaner than most of the alternatives, at least the way I tend to design stuff.

For some alternate views and good food-for-thought:
Model View Controller (featuring some alternatives and similar concepts) and the interesting and pertinent discussion What's A Controller, Anyway?.


This is design - there's really no right and wrong so much, but there are cleaner and uglier ways to do things. My personal opinion is that the Controller-as-Complement-of-View paradigm is one of the cleaner. That may vary depending on A) how much more one knows about design than I do and B) the way the rest of the system is designed. In short, YMMV [smile]
LessBread
LessBread
Here's another take on MVC, with example code, The Generic Windows Program.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
DudeMiester
DudeMiester
The way I see it, the model is the "real" program that maintains the data and does the calculations, sometimes referred to as the program kernal. The view is the GUI, mouse, printer, file system, etc... In other words, where ever the inputs and outputs of the model come from and go out to. The controller is just the glue code that translates between your model and your view. Therefore, you may have a variety of models and views that you can swap in and out, but your controller is going to be specific to every combination of model and view you have, since you need to re-apply the "glue" with each new combination.

imho, you should always minimise the average amount of glue (controller code) necessary when your model/view is combined with another model/view. A well designed interface should do this naturally.
[s] [/s]
I can see the fnords.
FxMazter
FxMazter
Hey acid2!

What you described, "The controller is then something that has different actions" is somewhat how I would liket to see a controller.

If you look at the PhonebookGUIListener, it is meant to only contain different actions that can be completed by the graphical View.

For example, Reasonable actions in a Phonebook GUI would be:

Add a phonebook entry
Remove a phonebook entry
Edit a phonebook entry
Show a phonebook entry somewhere

interface PhonebookGUIListener{  public void onGUIAddPhonebookEntryEvent(AddPhonebookEntryUI ui)  {    //fetch the model and add an entry:    ui.getInput().getName();    ui.getInput().getAdress();    ui.getInput().getPhoneNumber();    model.addEntry(name, adress, phoneNumber);  }  public void onGUIRemovePhonebookEntryEvent(RemovePhonebookEntryUI ui)  {    //fetch the model and remove an entry:    phoneNumber = ui.getInput().getPhoneNumber();    entry = model.getEntryByPhoneNumber(phoneNumber);    model.removeEntry(entry);    //note that that we shouldn't have to update any graphics in the view, as    //this should be messaged by the model to the view, which updates itself.    //Maybe by a View::onPhonebookEntryAdded(...);  }  public void onGUIRemovePhonebookEntryEvent(EditPhonebookEntryUI ui)  {    //fetch the model and edit an entry    ui.getInput().getName();    ui.getInput().getAdress();    ui.getInput().getPhoneNumber();    model.editEntry(newEntry);    //note that that we shouldn't have to update any graphics in the view, as    //this should be messaged by the model to the view, which updates itself.    //Maybe by a View::onPhonebookEntryEdited(...);  }  public void onGUIShowPhoneBookEntry(ShowPhonebookEtnryUI ui)  {    //A request to show a phonebook entry in some view that     //is supposed to graphically represent a phonebook entry    //possibly there    model.getSelectionModel().getLastSelected();    lastSelected.getName();    lastSelected.getAdress();    lastSelected.getPhoneNumber();       ui.showPhonebookEntry(name, adress, phoneNumber);  }}


As you see, you could add more complex actions to this interface. So basically, you would let the View still be a controller of some sort. But it would only control specifics for the current implementation of the view.

For example, If I implement a Swing view for the phonebook... the view will control the events from the buttons etc... and then it will delegate the actions to be performed to the PhonebookGUIListener.

I mean, I think it's reasonable to say that the View should know what actions should be taken when you press some button.

Example:

class MySwingPhonebookGUI{  public MySwingPhonebookGUI()  {    addButton.addListener(MyOnAddButtonListener);    phoneBookTable.addSelectionListener(MyOnPhonebookEntrySelectedListener);  }  ... MyOnAddButtonListener ...  {    onButtonPressed(...)    {      //The view must know what should happen when this button is pressed      //But how/the actual implementation is hidden from it, since only the      //controller knows that            AddPhonebookEntryUI addEntryUi = new SwingButtonAddPhonebookEntryUI(addButton);      //We must also know which input is relevant for this kind of action      addEntryUi.setNameInput(new NameInput(nameTextField));      addEntryUi.setAdressInput(new AdressInput(adressTextField));      addEntryUi.setPhoneNumberInput(new PhoneNuberInput(phoneNumberTextField));      guiListener.onGUIAddPhonebookEntryEvent(addEntryUi);  }  ... MyOnPhonebookEntrySelectedListener...  {    onSelection(...)    {      //The view must know what should happen when a Phonebook entry is selected      //In the table that shows the phonebook            ShowPhonebookEtnryUI showEntryUi = new SwingTextAreaShowPhonebookEtnryUI(myShowTextArea);      //We must also know which input is relevant for this kind of action...      //No imput is to be known by us...      guiListener.onGUIAddPhonebookEntryEvent(addEntryUi);  }}


So as you can see, the MySwingPhonebookGUI works as a semi Controller that handles input for the current implementation.

While the PhonebookGUIListener, knows how to handle the actions to be taken on user input in a general manner.

So now you could implemnet:
ShowPhonebookEtnryUI - as a JTextArea, or as a JTextField, or maybe you want to change it all together to a console view...

It's not quite the controller that you guys are expecting, from what you described ;)

What do you think?
sprawl
sprawl
Hi,

From my understanding your proposed controller is more like the model in the traditional MVC pattern. My view of MVC is more like ApochPiQ's.

The view renders the model.
The controller acts on events from the view (button clicks, scrolling, fetching records, whatever...).
The model consists of the data. Also the model has supportive logic as u describe in your controller, such as:

"Add a phonebook entry
Remove a phonebook entry
Edit a phonebook entry
Fetch a phonebook entry"

thats my five cents...

/sprawl

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.