I was reading about code architecture and the MVC/MVVP paradigm. Ideally, we should have the model as a high-level policy/component where it should not know or directly depend on other components, such as the view. Essentially, one of the roles of the controller is to send inputs to the model and thus has the model component as a dependency. However, we need the model needs to communicate with controller whenever it's state changes. From my understanding, we shouldn't have the model depend on the controller as it would we would create a bidirectional dependency between the components, which can lead to unmaintainable code and difficulty adding changes. So, I imagine the bidirectional relationship to communicate as the following:
However, if we create an interface for the model to communicate with the controller, IController
, it can remove this bidirectional communication. IController
implements all the methods that notify the controller changes. The dependency would look like the following:
Single Directional Relationship
Now, the model is ignorant of the actual implementations of the controller. Therefore, changes in the controller, should not affect the model components. I was wondering if adding an interface for the controller the best way for model and controller to communicate with each other.
I am also aware that in some programs, the model can directly communicate with the view directly using the observer design pattern. However, the model should not know the implementation details of the view since the model should be respected with high-level policy and should not know about low-level policies, such as the view. Therefore, in this case, let's not consider the observer pattern for the model to communicate the view.
-
3Why are you eliminating the observer pattern from consideration?Robert Harvey– Robert Harvey10/12/2017 02:49:06Commented Oct 12, 2017 at 2:49
-
Good question. The model should not know the implementation details of the view since the model should be respected with high-level policy and should not know about low-level policies, such as the view. Therefore, in this case, let's not consider the observer pattern for the model to communicate the view.mtber75– mtber7510/12/2017 03:20:51Commented Oct 12, 2017 at 3:20
-
@mtber75: The observer pattern is not just for communicating changes from the Model to the View, but for any case where one component must send updates to an unspecified number of other components and/or without a direct dependency between the components.Bart van Ingen Schenau– Bart van Ingen Schenau10/12/2017 07:30:23Commented Oct 12, 2017 at 7:30
-
1MVVP? what does it stand for?Ewan– Ewan10/12/2017 08:20:37Commented Oct 12, 2017 at 8:20
-
1Note that you can raise an event on a Model (and have any controller subscribe to that event) without the model having any knowledge of the controller.Robert Harvey– Robert Harvey10/12/2017 15:01:25Commented Oct 12, 2017 at 15:01
2 Answers 2
The Model knowing about, or being dependent on the Controller or View is not normally a problem in MVC.
In MVC the controller and View depend on the Model. Thus the model has no need for any dependency on anything.
You can even go further and get rid of the View's dependency on the Model, by creating and populating it in the Controller. Which is standard for web applications.
These methods do give you a problem for the case where the Model updates outside of a Controller event. For example, lets say the model has a Time property which updates automatically to the system time every second.
In these cases you will wish to update the view without having a controller event. This can be achieved by a number of methods
- Have the Controller or View raise a periodic event every second to update the view. eg a Timer object.
- Have something check for or be triggered by the underlying cause of the Model change and call the controller. eg a database trigger.
- Have the Model raise an Event when the event happens and have the Controller and/or view bind to this event. eg Model.OnTimeUpdate
Obviously the best solution is to avoid these types of uncaused changes in your Model. Usually there is a cause of the change, and you can route that cause through a controller, thus capturing the event and removing or exposing a dependency of your Model at the same time.
MVVM - Model View ViewModel takes this further by Binding the View to events raised by the ViewModel and vice versa. This may suggest extra Events be added to the Model in order to further leverage this pattern, but such events are by no means required, nor do they require any dependencies be added to the model.
-
2I like your third bullet. I think there might be some misconceptions about the Event here; you can raise an event on a Model (and have any controller subscribe to that event) without the model having any knowledge of the controller.Robert Harvey– Robert Harvey10/12/2017 14:59:49Commented Oct 12, 2017 at 14:59
-
You guys answered my question right on the spot :). Thanks. I've implemented in javascript of the
model
notifying thecontroller
its changes. Basically, themodel
has a notifier callback/higher-order function where it's input is a state that has been changed within the model. This callback function is called whenever a state of the model is mutated. Thecontroller
knows themodel
and will set the callback function with one of its own functions. Consequently, whenever thestate
of the model changes, thecontroller
will get notified and run one of its methods.mtber75– mtber7510/13/2017 18:55:22Commented Oct 13, 2017 at 18:55
NotifyControllerChanges()
should be an event, to which any controller in your system can subscribe. It would be part of the public API of your model, not an implementation detail. The model does not know (and does not care) who subscribes to it, and therefore has no knowledge of the subscriber.
If this still bothers you, then consider that the other methods on the model that you call from the controller must still know where to return to, yet we still treat them as having "no knowledge of the controller."