MVC - do I need to use a controller in a view?

As I know in the standard MVC implementation, we pass Controller and Model to View

But I do not agree with this idea a bit. I donโ€™t want my opinion to know about the controller and the model (oh no, maybe a needs model is sometimes needed, but Iโ€™m sure that he can live without the knowledge of the controller)

In my opinion, the Controller must control the View and Model, and the model does not need to know about the controller and the view; view does not need to know the controller (I do not exclude the model, because some implementations of the views must know about the model in order to listen for changes in the model). So my idea is that the view does not need to know about the controller .

1. Here is one example:

public class MyView implements ButtonClickListener { private Controller myController; private Button myButton; // I commented out the model because we dont need it now // we are talking about using controller in the view public MyView(Controller c/*, Model m*/) { myController = c; myButton = new Button(); // lets say that it is "register" button myButton.setOnButtonClickListener(this); } public void setRegisterButtonText(String text) { myButton.setText(text); } @Override public void onClick() { myController.tellToModelToDoSomething(); } } 

And the controller:

 public MyController implements Controller { private Model model; private View view; public MyController(Model model) { this.model = model; this.view = new MyView(this); } public void tellToModelToDoSomething() { model.doSomeActions(); } } 

2. And now, as I see this implementation, without passing the controller:

My view:

 public class MyView { private Button myButton; public MyView() { myButton = new Button(); } public void setRegisterButtonText(String text) { myButton.setText(text); } public void setOnRegisterButtonClick(final Command command) { myButton.setOnButtonClickListener(new ButtonClickListener() { @Override public void onClick() { command.execute(); } }); } } 

Command line interface:

 public interface Command { void execute(/*also can handle extra params*/); } 

And the controller:

 public MyController implements Controller { private Model model; private View view; public MyController(Model model) { this.model = model; this.view = new MyView(); view.setOnRegisterButtonClick(command); } public void tellToModelToDoSomething() { model.doSomeActions(); } private Command command = new Command() { public void execute() { tellToModelToDoSomething(); } }; 

}

So why I think using a controller in a view is NOT GOOD :

We mix the controller and look at the implementations, creating new dependencies.

I also think that the View should contain only VIEWS and operations with them (and the use of the controller, and some of its methods are already similar to the logic).

In the first example, the view tells the controller what to do. Do you agree? It seems that control is controlled by the controller!

In the second example, the controller controls what to do, and simply says what needs to be done if some button (only the view knows which button will be) clicked

I always used the second scheme, but after reading a new book about mvc, which says that we need to pass the controller to the view, I'm a bit confused.

Could you help me understand why I am mistaken and show some examples?

+6
source share
1 answer

There is no MVC standard since there are many implementations. Here is one interpretation of MVC that has been taught in many textbooks:

The definition of the controller in this interpretation is that it processes events from the view, so the view must use the controller.

In the standard MVC model contains and provides data, the controller manipulates the model and receives events from the view, and the view represents the model and generates events for the controller.

MVC is considered a transactional system where a transaction is triggered by an event. Typically, transactions look like this:

  • An event is created in the view (for example, a click on a button).
  • Event information is passed from the view to the controller.
  • The controller calls methods on the model to change it (setters and other manipulation methods that can update some database).

These first steps are the VC link and the MC link. VC exists because events are passed from the view to the controller that needs to be processed, rather than directly processing the view. The MC link exists because the model is updated by the controller in accordance with the event that was triggered.

Hence two ways. First:

  • The transaction is completed.
  • Separately, the model fires its own events to indicate that it has changed.
  • The view listens to the model and accepts the event, and also updates its representation of the model to reflect the changes.

This first path is one interpretation of the MV reference. The MV link is 1) a view that receives information from the model for its data, and 2) a model that informs the update, since it has been changed.

The second way is just one step: after the controller has processed the event, the view is immediately updated, simply updating all its interface elements. This interpretation of the MV connection is that the model simply provides its information for presentation, the same as point No. 1 from the MV line in the first path above.

Here are some of your code modified for the MVC architecture that I described:

 public class MyView implements View, ModelListener { private Button myButton; private Controller controller; public MyView(Controller controller, Model model) { myButton = new Button(); myButton.setOnButtonClickListener(new ButtonClickListener() { @Override public void onClick() { controller.onRegisterButtonClick(); } }); this.controller = controller; model.addModelListener(this); } public void setRegisterButtonText(String text) { myButton.setText(text); } public void modelUpdated(Model model) { // Update view from model } } 

And the controller:

 public MyController implements Controller { private Model model; private View view; public MyController(Model model) { this.model = model; this.view = new MyView(this, model); } private void manipulateModel() { model.doSomeActions(); } public void onRegisterButtonClick() { maniuplateModel(); } } 

Then the model:

 public class MyModel implements Model { private List<ModelListener> modelListeners = new ArrayList<ModelListener>(); public void addModelListener(ModelListener ml) { if (!modelListeners.contains(ml)) { modelListeners.add(ml); } } public void removeModelListener(ModelListener ml) { modelListeners.remove(ml); } public void doSomeActions() { // Do something fireUpdate(); } private void fireUpdate() { // Iterates backwards with indices in case listeners want to remove themselves for (int i = modelListeners.size() - 1; i >= 0; i-- { modelListener.modelUpdated(this); } } } 

ModelListener pretty simple:

 public interface ModelListener { void modelUpdated(Model model); } 

This is just one interpretation. If you need further isolation between the various parts, you should study the Presentation, Abstraction, Control (PAC) template. It is more decoupled than MVC, and great for distributed systems. It overwhelms simple web apps, mobile desktop apps, but some client and server apps and most cloud apps can benefit from this approach.

In PAC, you have three parts, representation, abstraction, and control, but abstraction and representation (model and representation) do not interact with each other. Instead, information passes only in the control module and leaves it. In addition, you can have several PAC submodules that interact with each other only through their controls, providing yourself with a good template for distributed systems. In principle, the control module is the main center of any data transfer.

Essentially, your interpretation of MVC may differ from mine or yours. The important thing is that you choose an architectural pattern and follow it to support your code in the future. And you are right that there are ways to separate MVC further. In fact, your example is a bit like a PAC, but instead of removing the VC link, it removes the MV link.

In any case, follow the architecture, document your architecture (so that people know what your interpretation is) and do not deviate from it.

+11
source

Source: https://habr.com/ru/post/925593/


All Articles