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 Model
at 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?
1 Answer 1
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– Dennis02/26/2016 20:48:07Commented Feb 26, 2016 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– Dennis02/26/2016 21:29:25Commented Feb 26, 2016 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.– Daniel T.02/26/2016 21:45:11Commented Feb 26, 2016 at 21:45
Explore related questions
See similar questions with these tags.
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?Service
layer? Or are you suggesting that I should keepService
,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'?