Renzhentaxi Baerde
Renzhentaxi Baerde

Reputation: 556

mvc where to keep the reference to controllers?

In my program the controller just hooks keypresses with a function. So should ikeep a reference to it? E.g. keeping a reference

Model model = new Model();
View  view  = new View(model);
Controller controller = new Controller(model,view);

or no

Model model = new Model();
View  view  = new View(model);
new Controller(model,view);

Inside Controller

public Controller(Model model, View view)
{
    this.model = model;
    this.view = view;
    view.setOnKeyPressed(this::doSomething);
}

public void doSomething(KeyEvent event)
{
    System.out.println("key pressed");
}

Maybe I implemented the Controller class wrong and misunderstood mvc pattern. But with what i wrote so far there is no reason for me to keep a reference to the controller object.

Upvotes: 4

Views: 2326

Answers (2)

James_D
James_D

Reputation: 209358

I'm not sure this question is really answerable, as it is probably too broad and/or too opinion-based. However...

MVC is a very loosely defined pattern. It really goes back about 40 years (or more) to the very early days of research into GUI development at Xerox PARC. Since it's been around so long and its primary use case (GUI architecture) has evolved significantly, it has branched into a number of sub-patterns and variations. Consequently, you'll find that "MVC" means many different things to different developers. In particular, MVC in a web application environment is somewhat different (imo) to MVC in the context you are talking about, because in a web application environment it has to sit on top of the request-response cycle. The rest of this answer/discussion focuses on the original "thick client" version of MVC, in which the view and controller are both in memory within the same process,and can communicate directly (rather than via a request-response protocol such as HTTP).

For me, the definitive guide to MVC in a desktop GUI context is Martin Fowler's essay on GUI architectures.

I would say that "classical" MVC is characterized by:

  • Having three components:
    • A model, which provides access to the data, may provide mechanisms for registering listeners for notification of changes to the data, and has no knowledge of the presentation of the data
    • A view, which observes the data in the model and updates itself when the data changes (this distinguishes classical MVC from some forms of MVP)
    • A controller, which provides the "view logic": typically this means it responds to user input and updates the model (not the view) as a result

So the model should know nothing at all about the view and the controller. The view doesn't know anything about the controller, but needs a reference to the model so it can display the data, and observe the data for changes, updating the presentation accordingly. The controller also needs a reference to the model, so it can update the data according to user input. Usually, the controller also needs a reference to the view, as it typically needs to register event handlers with the widgets in the view in order to know about user input it has to process.

The driving force behind this design is to allow multiple presentations (think of presentations as a combination of a view and controller) of the data which are kept synchronized. The pattern achieves this by referring everything though the model: one presentation's controller might update the model; since all the views observe the model, they all see those changes and each responsible for updating themselves accordingly. The controller that changed the view does not need to know about any other views that may be observing the data in order to keep all views in sync.

Your application itself will certainly need access to the model; it probably needs to access the data, maybe modify it from external (i.e. not user-driven) factors, persist the data at shutdown, etc. Your application probably needs access to the view (it needs to display it somewhere, may need to dispose of it at shutdown, etc). Your application may or may not need access to the controller. In its purest form, once the controller knows how to observe the view for user events, and knows how to update the model, you never need to communicate with it again. (If you want to change states from "external" events, you do so through the model, not through the controller(s).)

Several variations of this idea have emerged (see Fowler). One popular one (which also have several variations of its own) is Model-View-Presenter. In this variation, the controller is replaced by a "Presenter" which takes on some, or even all, of the responsibility of updating the view. In one form of this (which Fowler calls "Passive View"), the view is completely free of logic and merely lays out the controls. The presenter processes user input, updating the view and the model when user input occurs on the view, and observes the model, updating the view if it changes. This variant has advantages in terms of testability and ability to debug, but there is arguably tighter coupling between the view and presenter than there is between the view and controller. (It is relatively easy to provide multiple controllers for a view; providing multiple presenters for a passive view gets much more complex, and the presenters usually have to have some knowledge of each other.)

JavaFX actually provides "out-of-the-box" support for this style of architecture, using FXML as a (usually passive) view, and providing convenient ways to hook into what it calls the controller (which is perhaps more of a presenter). JavaFX properties make it easy to write models which can readily be observed by a view or by a presenter as needed.

In practice, you'll usually find a hybrid of these works best in most cases. A medium-large scale application will use MVC/MVP-type patterns in multiple places, on multiple different scales. You will often find that it is convenient for the controllers/presenters to have some knowledge of each other and to communicate between them, in which case you will obviously need to keep references to the controllers.

So the answer to your question is probably just "it depends what you need". If you don't need a reference to the controller, there is no need to keep one. Indeed, in the standard use of FXML in JavaFX, the controller class is simply specified in the view (the FXML); the FXMLLoader instantiates the controller from that information and wires the view and controller together as needed. You often never even have a reference to the controller instance in your code at all. Though, as seen in this popular JavaFX question you can certainly get one if and when you need. In a completely "pure" classical MVC, all state change is made through the model, and the views observe it, so you would never need access to a controller. Fowler points out some nice examples where this doesn't work as cleanly as it sounds: firstly that some state, and associated logic, is really part of the view and has no place in the model, and secondly that the registration/notification mechanisms can make it very hard to debug your application.

Upvotes: 8

Dhruv Rai Puri
Dhruv Rai Puri

Reputation: 1375

You will need for a controller instance be created for you when a key is pressed on the GUI. So you will need it to be a Listener which listens to key presses.

Once you have a GUI listener registered, its the framework's responsibility to instantiate that controller and pass the view to that controller.

(So, you never need the handle to a controller - its handle is always with the framework.)

Next, when you are in the controller with the view, you determine which model to create or fetch based on the values in the view...

This is how all MVC's work...

Upvotes: 0

Related Questions