There are no commonly-agreed-upon (i.e. defacto) design guidelines for MVC. It is not that entirely hard to do it yourself but requires some planning on your classes and lots of time and patience.
The reason there is no definite solution is because there are multiple ways to do MVC, all with their pros and cons. So just be smart about it and do what suits you the best.
To answer your question, you actually want to decouple the controller from the view as well (so you can use the same business rule logic for both a Swing app and in the console app). In the Swing example you want to decouple the controller from the JWindow
and whatever widget in Swing. The way I used to do (before using actual frameworks) is to create an interface for the view that the controller uses:
public interface PersonView {
void setPersons(Collection<Person> persons);
}
public class PersonController {
private PersonView view;
private PersonModel model;
public PersonController(PersonView view, PersonModel model) {
this.view = view;
this.model = model;
}
// ... methods to affect the model etc.
// such as refreshing and sort:
public void refresh() {
this.view.setPersons(model.getAsList());
}
public void sortByName(boolean descending) {
// do your sorting through the model.
this.view.setPersons(model.getSortedByName());
}
}
For this solution during startup you need to register the controller into the view.
public class PersonWindow extends JWindow implements PersonView {
PersonController controller;
Model model;
// ... Constructor etc.
public void initialize() {
this.controller = new PersonController(this, this.model);
// do all the other swing stuff
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// TODO: set the JList (in case that's you are using)
// to use the given parameter
}
}
It might be a good idea to create an IoC-container to do all the setup for you instead.
Anyhow, this way you can implement console-only views, using the same controllers:
public class PersonConsole implements PersonView {
PersonController controller;
Model model;
public static void main(String[] args) {
new PersonConsole().run();
}
public void run() {
this.model = createModel();
this.controller = new PersonController(this, this.model);
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// just output the collection to the console
StringBuffer output = new StringBuffer();
for(Person p : persons) {
output.append(String.format("%s%n", p.getName()));
}
System.out.println(output);
}
public void createModel() {
// TODO: create this.model
}
// this could be expanded with simple console menu with keyboard
// input and other console specific stuff
}
The fun part is how to do event handling. I implemented this by letting the view register itself to the controller using an interface, this is done using the Observer pattern (if you're using .NET you'd be using event handlers instead). Here is an example of a simple "document observer", that signals when the a document has been saved or loaded.
public interface DocumentObserver {
void onDocumentSave(DocModel saved);
void onDocumentLoad(DocModel loaded);
}
// in your controller you implement register/unregister methods
private List<DocumentObserver> observers;
// register observer in to the controller
public void addObserver(DocumentObserver o) {
this.observers.add(o);
}
// unregisters observer from the controller
public void removeObserver(DocumentObserver o) {
this.observers.remove(o);
}
public saveDoc() {
DocModel model = model.save();
for (DocumentObserver o : observers) {
o.onDocumentSave(model);
}
}
public loadDoc(String path) {
DocModel model = model.load(path);
for (DocumentObserver o : observers) {
o.onDocumentLoad(model);
}
}
That way, the view can properly update itself since it is subscribing to the document updates. All it has to do is to implement the DocumentObserver
interface:
public class DocumentWindow extends JWindow
implements DocView, DocumentObserver {
//... all swing stuff
public void onDocumentSave(DocModel saved) {
// No-op
}
public void onDocumentLoad(DocModel loaded) {
// do what you need with the loaded model to the
// swing components, or let the controller do it on
// the view interface
}
// ...
}
I hope these motivating examples gives you some ideas on how to do it yourself. However I strongly advise you to consider using frameworks in Java that do most of the things for you, or else you'll end up having a lot of boilerplate code that takes a long time to write. There are a couple of Rich Client Platforms (RCP) that you could use that implement some of the basic functionality that you most likely need, such as application-wide document handling and a lot of basic event handling.
There are a couple I can think of from my head: Eclipse and Netbeans RCP's.
You still need to develop controllers and models for yourself, but that's why you use an ORM. Example would be Hibernate.
IoC containers are cool'n all, but there are frameworks for this as well. Such as Spring (which also does data handling as well among other things).
This is an ancient debate really. It goes all the way back to the first databases and the notion of "referential integrity", which in turn is a variation of the strong-typing / weak-typing debate.
Who's job is it to make sure that data is stored in a consistent and "known good" manner? MVC purists will tell you it's the controller's job. Database architects will tell you it's the model's job (or even the database's job). Ux people might even tell you it's the view's job! Big Data guys may say "It's the person using the data's job."
After being a software engineer / architect / developer for 20+ years, I've come to the conclusion that often the concern is important, but how you solve it is less important, so long as you decide on an approach and maintain it. So, my advice would be something like: rather than asking for people's opinions on dogma about it, think through solving the "who owns validation?" discussion using three different approaches: model, view, and controller. Think about how your app will behave if you solve it those three different ways. Will your end users be satisfied with all three approaches? Chances are, depending on where you put this, your end users will experience something different. Do they have an opinion? Also, which route costs you the most in terms of time and money? Which will be easier to maintain and explain to new people? What about security? All of these things are important considerations when designing a system, and dogmatic answers don't factor these things in -- they substitute a common pattern for your precise context. Sometimes that's a good idea, sometimes it's a shoe-horn disaster. Only you can figure out which applies.
Best Answer
MVC does not tell you how small to make the models.
For a spreadsheet, when you find that passing the whole data structure between a View and a Model is too slow, or makes the code too complex, you could make an MVC triad to represent something as small as a single cell.
The model part of the cell could then connect in some appropriate way to a larger business object that represents the entire sheet.
Similarly, the cell views will be embedded in another view to represent a sheet, or a window onto a sheet.
Update
The main aim of MVC is not to improve performance, but to make the code more understandable, and therefore easier to maintain.
If you make an MVC triad for each individual cell, this should be easier to understand and modify than if the triad represents a whole column, or the entire sheet. However, performance may suffer for changes that affect the entire sheet, as you may end up with many small objects sending messages to each other.
One alternative to MVC that you might also want to consider if you want to avoid passing data between Views and Models is direct manipulation. In direct manipulation, the object the user interacts with is the object that stores the business data (the cell value) and the business rules (how the cell value can change.)