0

I've learned MVC (model-view-controller) but I've been unable to figure out how to implement it in a way that respects encapsulation between the three components.

For example, I was always taught that the front end and back end should be completely separate, and should never interact. But in MVC, the Model actually mutates the view, which means the model has a reference to the view.

Similarly, the controller needs to take in input from the front end (ex. button, text box, etc) and mutate the model. How can the controller be both separate from the view AND have its components (button, text box) inside of the view (otherwise they wouldn't be shown to the user). Wouldn't this mean the view would have to be mutable?

I asked my professor about this, and pointed out some violations in abstraction and encapsulation with MVC and he responded by saying that "it is part of the design, to responsibly use references to the view and model. If someone designing the model happens to take advantage of the lack of encapsulation of the view, then it violates the contract of the design."

Is there a way to implement MVC in a way where no one component can cause harm to another (ex. model cannot delete the scene of view, controller cannot null-out all data inside of model, etc etc). Is the key just to setup many accessors/mutators in view & model?

Hatefiend
  • 3,416
  • 6
  • 33
  • 74

3 Answers3

-1

When I implement MVC, the Model has neither access to the Controller or to the View. In fact, I try to limit the model to simply being raw data - like a copy of a record from a database. Simple, light-weight.

The Controller is my wrapper around the Model and is where all the heavy duty logic sits. It alone is responsible for modifying the underlying Model (if editable), carrying out corresponding business logic, and for raising events when things change. The Controller has no direct access to the View (there may be several): instead the View invokes Controller functions and updates it's properties. The Controller may also "massage" the raw Model data into a format that is more easy for the UI layer to interact with.

The View has no direct interactions with the Model. It updates in response to events from the Controller. User-interactions (like editing a text-box, clicking a button, etc) generally get re-directed to the Controller. The UI layer should only care about UI-specific work.

Thus you have a nice layered software architecture: UI -> Business Logic -> Data. Nothing can directly interact with the layer on top of it - only indirect interactions through events are permitted. You can also pass around the same Controller instance to multiple Views so that they stay in sync.

  • This is not MVC. See Wikipedia, or the answer from @Kata. – jaco0646 Nov 05 '18 at 15:48
  • @jaco0646 - This is false. Models can just be pure data in MVC. You can also give them some limited behavior (like data change events) - but most of the logic goes into the Controller. As it states on wikipedia: 1. The model is responsible for managing the data of the application. It receives user input from the controller. 2. The view means presentation of the model in a particular format. 3. The controller responds to the user input and performs interactions on the data model objects. The controller receives the input, optionally validates it and then passes the input to the model – Ryan Pierce Williams Nov 05 '18 at 16:30
  • Additionally, the model updates the view whenever its data changes. The controller does not update the model and then update the view. The flow goes round a circle, as the diagram shows. – jaco0646 Nov 05 '18 at 16:38
  • Yes the data change event commonly goes into the data layer, this would be the one discrepancy with what I did above. The View doesn't actually care about where the event comes from, however, it is simply important to that the View be updated via an event. Since the Controller is in charge of modifying the data - and never the View - it is reasonable that the Controller would fire such events, since it always knows and initiates such changes. Also, MVC refers to a family of programming models, with lots of such variations (MVP, MVVM, etc) where you do see the controller fire events. – Ryan Pierce Williams Nov 05 '18 at 16:50
  • Here's a derivation of MVC: Model-View-Presenter (MVP) where, as you can see in the diagram, the View is updated via events from the Controller/Presenter layer: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter – Ryan Pierce Williams Nov 05 '18 at 16:54
  • MVC is one of the most quoted (and most misquoted) patterns around. Confusing between MVC (software pattern) and 3-tier architecture (deployment pattern) is one of the most popular misunderstading. – Nghia Bui Nov 05 '18 at 16:57
  • @Kata - perhaps, but no one is referencing a 3-tier deployment pattern above. These are just variations of the MVC software pattern. – Ryan Pierce Williams Nov 05 '18 at 17:07
  • If this answer is meant to describe MVP, then my only issue is in calling it MVC. Conflating the two patterns is misleading. They may be similar, but the names are not interchangeable. The answer should be edited to make it clear that MVP is what's being described. – jaco0646 Nov 05 '18 at 17:12
  • Regardless of variants, all business logic belong to Model. When you say "Models can be pure data (no logic)" and "most of the logic goes into the Controller", isn't it 3-tier? – Nghia Bui Nov 05 '18 at 17:12
  • @Kata - these are all 3-tier SOFTWARE models, not deployment models. This says nothing about where the data is stored (eg, a database), where the business logic is performed (a separate server?), etc. However, upon searching online there does appear to be some common confusion and debate about whether the business logic should go in the Controller or the Model - so perhaps I'm in error there. – Ryan Pierce Williams Nov 05 '18 at 17:19
  • The following question has some more informative answers about what constitutes as "business logic" and where it should go: https://stackoverflow.com/questions/4415904/business-logic-in-mvc A popular view from these answers appears to be that MVC is about structuring the front-end/presentation layer of the application, and that there will be additional patterns under that where the business logic actually lives. They break it up into Domain vs Application logic, etc. Also some good examples of interaction between Controller <-> Model interaction. – Ryan Pierce Williams Nov 05 '18 at 17:29
  • Also, @Kata - I need to correct my earlier statement. These are not 3-tier patterns, but 3-layer patters. The difference being that a tier refers to a physical separation of concerns, while a layer is merely a logical/conceptual separation of concerns (https://en.wikipedia.org/wiki/Multitier_architecture#Comparison_with_the_MVC_architecture) – Ryan Pierce Williams Nov 05 '18 at 17:42
  • 2
    Glad to hear that! Actually these days I don't mind to focus too much on these stuff of terminologies. Just design your program so that it is easy to manage and reuse, that's it! So, if you want to put business logic into Controller, go ahead. But in the future, if you want to reuse that logic in another environment which does not require UI, or requires a different UI, then you should extract that logic into Model. – Nghia Bui Nov 05 '18 at 17:52
-1

Model objects are not dumb data, they are true objects with behaviors. So Controller cannot null-out data of Model as you said. The job of Controller is just converting input sent from View, to a format that can be understood by the behaviors exposed by Model. If the converting succeeds, Controller will pass the converted input to Model. Otherwise, Controller will directly notice to View without bothering Model.

Model also cannot directly mutate View as you said. Model keeps an indirect reference to View: Model does not depend on the View type but depends the interface implemented by View. Model just notices the output to View. How View responds (like deleting a scene) to the received output is up to View.

Letting objects directly mutate data of other objects is a very bad practice in OOP.

Nghia Bui
  • 3,694
  • 14
  • 21
  • Thanks for the reply. Can you show a brief example of what you mean by `"Model keeps an indirect reference to View"`? – Hatefiend Nov 04 '18 at 06:44
  • `class Model { private OutputPort op; public Model(OutputPort op) { this.op = op; } }` ... `interface OutputPort { void setResult(String result); }` ... `class View implements OutputPort { public void setResult(String result) { this.resultLabel.setText(result); } }` ... You may find this article interesting http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html – Nghia Bui Nov 04 '18 at 07:05
  • @Hatefiend, the relationship between model and view is the [Observer Pattern](https://sourcemaking.com/design_patterns/observer). – jaco0646 Nov 05 '18 at 15:56
  • The Model shouldn't explicitly reference the View. The View should be informed of updates to the Model via events. The event source can either be the Model itself or else the Controller. – Ryan Pierce Williams Nov 05 '18 at 18:33
-2

Think of it as two separate applications:

Controllers live in one application. Their purpose is to accept input and/or create output. Both input and output are a Model, often the same one (after a bit of validation). Models are just dumb containers for the inputs and outputs.

You can unit test controllers completely independently. A test harness can just feed them input (and mock their dependencies) and check their output. Because Models are dumb, they don't even have to be mocked.

Views live in another application. Their purpose is to accept input and make a page look a certain way. The input, of course, is the Model.

In a clean MVC architecture, models are as dumb as DTOs. Models do not manipulate views or manipulate controllers; in fact, they are fine having no behavior at all. When you do it this way, there are no dependencies at all between View and Controller, and the Model acts simply as an interface. This is how you get encapsulation and separation of concerns.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • This answer is completely wrong. In MVC, "_The model is the central component of the pattern._" [Wikipedia](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) – jaco0646 Nov 05 '18 at 15:45
  • This answer is totally wrong. Model is about about business domain, including data/logics/behaviors or whatever belong to the domain. Controller and View are non-domain things: UI. – Nghia Bui Nov 05 '18 at 17:06
  • With respect, @jaco0646 and kata, your feedback is a too black and white given the complexity and history of MVC. Modern MVC is actually an adaptation of the Model2 pattern, and in this context the models serve the role previously assigned to ViewModel. Business logic is extracted to services which are injected into controllers, and may have their own "model" (domain objects), which is what I suspect you are referring to. But there is actually some debate about this as well. Will edit my post with references if I get some time later. – John Wu Nov 05 '18 at 17:26
  • I'm talking about the original MVC created by Trygve Reenskaug, which then echoed by Martin Fowler in his [book](https://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420) (chapter 14) and by Uncle Bob in his [article](http://blog.cleancoder.com/uncle-bob/2014/06/30/ALittleAboutPatterns.html). If the asker of this question clarifies that he wasn't mentioning about the original MVC then I will remove my comment. – Nghia Bui Nov 06 '18 at 03:38