Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

How flexible should the MVC implementation be?

 
Lasse Koskela
author
Sheriff
Posts: 11962
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi ranchers,
I am struggling with my MVC and would appreciate some opinions.
Some folks here have suggested that the coupling between View and Controller should be implemented with some kind of "hook" methods passing around XXXListener implementations.
Have I understood something fundamentally wrong or is this too much coupling? We are basically assuming that the View will be implemented as a Swing GUI. What if the GUI is to be replaced with a console interface? Unlikely, but still.
Another similar issue is the interaction between View and Model. A popular implementation seems to be having the View call Model.getTableModel(). Again, an assumption is made that the GUI will be implemented with a JTable. I know that the requirements insist using a JTable but again it might change.

I'm thinking of doing something like the following. Please comment.

/**
* Main class creates the three participants
* giving the required references to other parts
* of the MVC hierarchy.
*/
class Main {
// model is the starting point and gets a
// reference to the database
FBNModel model = new FBNModel(SomeDataAccessThingie);
// controller is given a reference to the model
// so that the controller can modify the model
FBNController controller = new FBNController(model);
// view is given a reference to the controller
// (for events) and to the model for getting
// updates (using observer pattern).
FBNView view = new FBNView(controller, model);
}

/**
* FBNController reacts to application
* specific events instead of Swing actions like
* java.awt.event.ActionEvent.
*/
class FBNController {
fbnActionPerformed(FBNAction) (
// manages application specific events
}
}

/**
* FBNView manages its own Swing/AWT events
* and calls the FBNController method
* fbnActionPerformed(FBNAction).
*/
class FBNView {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("foo")) {
this.controller.fbnActionPerformed(action1);
} else if (...) {
this.controller.fbnActionPerformed(action2);
} else if (...) {
this.tableModel.setXXX(this.model.getFlights());
}
...
}
}

/**
* FBNModel implements business logic. The
* interface contains no Swing-specific objects.
*/
class FBNModel {
Collection getFlights(FlightQuery query) {
// get the flights from DB
}
bookFlight(String flightNumber, int seats) {
// book the flight from DB
}
}
 
Chandu onwards
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey i haven't used MVC in my client design,
does that mean i would loose points here!!!
 
Lasse Koskela
author
Sheriff
Posts: 11962
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, my instructions don't dictate using MVC as such, but there is something that could implicate that "MVC would be a good thing":
"Your user interface should be designed with the expectation of future functionality enhancements, and it should establish a control scheme that will support this with minimal disruption to the users when this occurs."
MVC is one pattern that facilitates e.g. easier modifications to GUI without revolutionalising the other parts.
I'd like to hear about experiences on using/not using MVC and the grading these implementations have received...
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have I understood something fundamentally wrong or is this too much coupling? We are basically assuming that the View will be implemented as a Swing GUI. What if the GUI is to be replaced with a console interface? Unlikely, but still.

This is specifically why the Hook methods work, is because you can swap out any GUI you want at any time without disrupting all the classes. The only "Coupling" that occurs in my design is that the Controller, who controls everything, knows the GUI and the Model, and is the controller to pass the information back and forth. In this model the GUI knows nothing about anything.
You can also make the Contoller not know anything and use Action classes to Hook the GUI and Controller together.
Mark
 
Lasse Koskela
author
Sheriff
Posts: 11962
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Mark, that cleared your design in my eyes.
I'll take a second look at my GUI design after a good 10 hour sleep and decide which way to go.
...I have an initial implementation with View and Controller as a single class comprising approx. 700 lines ready for some heavy refactoring...

Lasse
 
Lasse Koskela
author
Sheriff
Posts: 11962
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another quickie...
Originally posted by Mark Spritzler:
The only "Coupling" that occurs in my design is that the Controller, who controls everything, knows the GUI and the Model, and is the controller to pass the information back and forth.

How does your Controller pass for instance flight search results to the GUI? I mean how does the anonymous Listener get a reference to e.g. a TableModel for setting the search results if the Listener is created at the Controller (who knows the View)? Does the GUI/View expose some public methods or member variables such as getTableModel()?

Lasse
 
John Smith
Ranch Hand
Posts: 2937
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

How does your Controller pass for instance flight search results to the GUI? I mean how does the anonymous Listener get a reference to e.g. a TableModel for setting the search results if the Listener is created at the Controller (who knows the View)?

One solution is to have the controller call a searchFlights() method on the model. After the model calculates the results, it fires a method that broadcasts the message to all observers (you seem to have already implemented this). A method parameter in that broadcast may be a list of flights. Subsequently, the update() method of the GUI is invoked, and the search results are sent to table model.
The advantage of this approach is that the controller doesn't need to know anything about GUI. If your JTable is replaced by some other component in GUI, only a few lines of code in one method in GUI will need to change. No changes to controller or model will be required.
Is that what you were looking for?
Eugene.
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Eugenes solution will work.
I call getTable() method, which is a public method in my GUI's TablePanel, I then create a new instance of my TableModel with the DataInfo[] I received from the Data, I then call setModel on the Table that returned in the getTable method, and I pass the new instance of my TableModel.
three lines of code.
Mark
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic