1

I have some code where Controller depends on the Model, and in my case Model acts like a Database Access Object.

use FQDN\Model;

class Controller
{
    /** @var FQDN\Model */
    private $model;

    function setModel(Model $model)
    {
        $this->model = $model;
    }

    function showPage()
    {
        // model is set up (injected) in constructor
        $data = $this->model->getData();
        return ViewModel($data);
    }
}

At first, in previous code iterations, my Model was NOT injected into my Controller and I was told that I should not just inject the Model as I did above, but do inversion of control to the point where Controller does not depend on Modelat all. Like so:

class Controller
{       
    /** @var array */
    private $data; //controller-specific data

    function setData(array $data)
    {
        $this->data = $data;
    }

    function showPage()
    {
        // data has already been injected into controller
        // Controller has been created via Factory Method
        // and populated with data
        return ViewModel($this->data);
    }
}

Controller is NOT aware of the model. Model is outside of Controller entirely. ControllerFactory (or ControllerBuilder) will instead:

  • create the Controller
  • invoke the Model
  • populate Controller with controller-specific data

I wanted to ask if there is a clear guideline for MVC that I should follow as far as having Controller depending on the Model, or having it specifically NOT depending on the model at all. Because even with dependency injection, my first code example still has code constructs inside Controller that make it aware of the model and hence dependent on it. I do not konw

Degrees of Separation

If you will I can define some degrees of separation from tighter coupling to looser coupling:

  • Model is instantiated inside the Controller (hardwired)
  • Model is injected inside the Controller via constructor or a setter (injected)
  • Model is instantiated inside the ControllerFactory, data extracted from the Model and passed into Controller (separated)

All will "work" but what can help me decide which one is best for which particular case. Or is there a clear guideline for this?

  • Have you considered using a Service Layer? – Robert Harvey Feb 26 '16 at 18:23
  • My Model is kind of like a service layer in my first example. Yes? I considered it as a Service because of the way it is called like $data = $this->model->getData(). I can call it a Service instead. Call it a "data service". I mean I can have several different services but my question remains ... if I call a "Model" a "Service". I mean what would be the difference? – Dennis Feb 26 '16 at 18:37
  • The Service Layer is part of the model, but it is not the model. What you decide to call it doesn't really matter. Read the Fowler article I linked. – Robert Harvey Feb 26 '16 at 18:40
  • Are you suggesting that I should introduce a Service layer? Or are you suggesting that I should keep Service, Model, Controller independent of each other? My question is, no matter how many layers are introduced, how do I 'connect them' to each other? Do I use dependency injection (which still keeps the dependency), do I keep them completely separate of each other, or is it really 'up to me'? – Dennis Feb 26 '16 at 20:32
  • Have you considered injecting your model directly into the showPage method? symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/… – Cerad Feb 27 '16 at 0:43
2

I don't think there is anything so clear cut as you might like, but "Tell don't ask" is close.

Tell objects what's going on, don't expect them to ask for what they need. In your first example, you are providing the model, but the controller still has to ask for stuff from it.

The optimum solution, IMHO is that the controller should observe the model, that way it can update whenever the model changes. The way you have it now, (in both of your examples,) the controller is completely ignorant of model changes when they occur. The ControllerFactory should set up the observation.

I think following the observer pattern would be best practice in this situation.

  • Thanks. I like the 'tell don't ask' idea. On observer pattern, I am not sure exactly how useful it is will be in a web application. for something like a Windows application, changes in the model can be dynamically updated on the UI, but in a web app typically you load the page, and that is what you get. However surely AJAX web app can still reap the benefits. That is actually pretty cool. I will have to think more on that. – Dennis Feb 26 '16 at 20:48
  • User triggers an event. Event is routed to a Controller. Controller engages the model and the service layer and gets response, which it pushes to the View. If a model is changed elsewhere, it also engages the Controller, which then also potentially engages the Model and the Service layers and then Controller pushes results to the View. Did I get this correctly? – Dennis Feb 26 '16 at 21:29
  • User triggers an event. Event is routed to a Controller. Controller informs the model. The model tells the service layer and view how it changed... Or if you are using the controller as a presenter, then the view tells the service layer and controller how it changed and the controller then tells the view how to change in response. It's a bounce back kind of situation. The View sends the user event to the controller which sends it to the model which sends it to the service layer and back to the controller, which sends it back to the view. – Daniel T. Feb 26 '16 at 21:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.