In MVC (non-web) the model is assigned to the view, either by the controller or earlier in the execution (a controller, model and view are instantiated all at once). The view has direct access to the model and calls methods on it.
Taking the example Jeff cited from Martin Fowler, it would look more like this:
class AlbumController {
private AlbumModel model;
//Java constructor
public AlbumController(AlbumModel model) {
this.model = model;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) {
this.model.setId(request.getParameter("id"));
}
}
And if we introduce a proper model
class AlbumModel {
private int id;
private Repository albumRepository;
//Let's use DI instead of static methods for the repository, I'll explain why shortly.
public AlbumModel(Repository albumRepository) {
this.albumRepository = albumRepository;
}
public void setId(int id) {
this.id = id;
}
public Album getRecord() {
return this.albumRepository.find(this.id);
}
}
The view would then contain the display logic to show a different set of HTML based on the type of object and it would call model.getRecord()
to retrieve the loaded record.
So why is this better? Well this isn’t, it contains the exact same problem that the original code does: It’s not reusable and incredibly specific. However, with a couple of minor changes:
class LoadRecordController {
private LoadRecordModel model;
//Java constructor
public LoadRecordController(LoadRecordModel model) {
this.model = model;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) {
this.model.setId(request.getParameter("id"));
}
}
interface LoadRecordModel<E> {
public void setId(int id);
public E getRecord();
}
class RepositoryModel<E> implements LoadRecordModel {
private int id;
private Repository repository;
//Let's use DI instead of static methods for the repository, I'll explain why shortly.
public RepositoryModel(Repository repository) {
this.repository = repository;
}
public void setId(int id) {
this.id = id;
}
public E getRecord() {
return this.repository.find(this.id);
}
}
Now suddenly the advantage is obvious. Using Jeff’s example, I need to create incredibly similar controllers for loading a single blog/user/product/category/post/topic/etc into a view based on its primary key. Using the above code I can reuse the same model/controller with only a different view (by passing the required blog/user/product repository into the model). Not only that, I can use a different model e.g. load a twitter post by ID via the twitter API by writing a second model that implements LoadRecordModel… or one that reads data from an XML file/CSV rather than a repositry using the same controller and view.
Web MVC puts the application state and display logic (deciding which view to use) into the controller, heavily reducing reusability as well as coupling the controller to domain concepts (repositories and entities)