How does an MVC system work?

2019-01-21 14:46发布

问题:

I'm trying to learn the MVC pattern, but each place say something different. So now I don't know whats the true MVC.

So I'm guessing its the most pure MVC:

  • Model is just data and notify data changes.
  • View reads the messages of the Model to update the view.
  • Controller reads the user input from View and changes the Model according.

Implementing

  • Model knows no one.
  • View knows the Model.
  • Controller knows both View and Model.

Pseudocode:

/* Model */
class Color{ 
  color = blue;
  setColor(color);
  notifyUpdate();
}
/* View */
class ColorPicker(model){
  model.register(update);
  update(){
    this.colorToExhibit = model.color;
  }
}
/* Controller */
class Colorize(view, model){
  view.register(update);
  update(color){
    model.setColor(color);
  }
}

Some questions:

  1. Is that right?
  2. I can't see why the View cannot change the Model directly, but through Controller.
  3. Suppose I have animations to be performed after an action. Who must handle this animation: the Model, the View, or the Controller? Also: the animation logic is part of the Model, View, or Controller? More: Suppose a Poker game. After the user choose an action (say, 'Raise'), the system must play an animation (say, the chips going from player spot to the desk). How can I see this poker example (with animation) as a MVC? Can you explain and give a pseudocode about that?

Thank you.

回答1:

  • Model is just data and notify data changes.
  • View reads the messages of the Model to update the view.
  • Controller reads the user input from View and changes the Model according.

The Model is more than just data. The model is also the business logic. It contains all of the intelligence of the system, or at least an abstraction of behind-the-scenes intelligence (such as database calls or other service calls). Consider the saying, "Keep your models heavy and your controllers light."

  • Model knows no one.
  • View knows the Model.
  • Controller knows both View and Model.

The Model knows no one, that it correct. The Model should be portable between applications and shouldn't depend on UI concerns in any way. (The View and the Controller are UI concerns in this case.)

The View knows the Model, also correct. The View basically "binds" to the Model. It presents all of the UI elements and places Model data within the UI elements accordingly.

The Controller kind of "knows the View." It knows which View to which it should direct control, but it doesn't know anything about that View. Nor does it know which View from which control previously came. The Controller responds to events. An event comes in from the UI, carrying some kind of state information with it (a ViewModel, perhaps), directs logical control through the Models (where the business logic happens), and responds with a Model (or a ViewModel, if the shape of the data specific to a particular View is different than the Models) and a View.

I can't see why the View cannot change the Model directly, but through Controller.

The View can manipulate the Model within the context of the user interaction, but shouldn't expect those changes to persist in any way. The View should be considered "client-side" and doesn't know anything "server-side." (Even if you're talking about a native application and not a web application.) Persisting any change is considered a UI "action" or "event" and would go to a Controller to make it happen.

Suppose I have animations to be performed after an action. Who must handle this animation: the Model, the View, or the Controller? Also: the animation logic is part of the Model, View, or Controller?

An animation sounds like an entirely UI-based operation. It would be within the View. Is there more happening than just a UI animation? Does the animation change anything in the back-end? For example, if I have a web application and, when a page loads, I want to fade-in some data (an animation)... that's entirely in the View. The data would be delivered to the View like any other data, and the animation takes place entirely within the UI (View). It doesn't do anything from the perspective of the Model or the Controller.

Suppose a Poker game. After the user choose an action (say, 'Raise'), the system must play an animation (say, the chips going from player spot to the desk). How can I see this poker example (with animation) as a MVC? Can you explain and give a pseudocode about that?

The action ("Raise") is a Controller event. The UI would contact the controller to perform the "raise". So the Controller might have a method like this:

View Raise(GameState state)
{
    // Interact with the Models to update the known state of the game.
    // The Models would perform the actual Poker game logic.
    // Respond with a View bound to updated Models.
}

Once the Controller responds to the UI with a new View, that View would contain any animations to display to the user. (After all, you don't want to perform the animation unless the action was successful, right? When the Controller responds to the UI with a new View indicating a successful action, then the animation would play. It may instead respond to the UI with a View indicating an error, in which case that View would show something else.)



回答2:

I'll go with the simple Bank analogy.

  • Tellers are Views.
  • Runners are Controllers.
  • Bankers are Models.

The Bankers are the smart ones, they know all of the business logic and do all of the complex calculations.

The Runners are used to transport the money (data) from the Bankers to the Tellers.

The Teller presents the money to the Customer.

A simple representation:

Model

public class BankAccount
{
     public int ID;
     public int Balance;

     public BankAccount(int id)
     {
         ID = id;
         Balance = DetermineAmount();
     }

     public int DetermineAmount()
     {
         // Gather transaction info, debits, credits and return a
         // sum of the amount left in the account depending on the
         // id provided.
     }
}

Controller

    public class BankAccountController
    {

         public ViewResult Index(int id)
         {
             BankAccount account = new BankAccount(id);
             return View(account);
         }

    }

View

<ul id="account-info">
   <li>Account ID: `@Model.ID`</li>    
   <li>Balance: `@Model.Balance`</li>
</ul>


回答3:

If you are interested in the historical true MVC, then start with Trygve Reenskaug. He created (observed?, catalogued??) it in the late 1970s. For a start, read "Models-Views-Controllers" from 1979. It defines the terminology. Take careful note of it's title - all three roles are pluralized. This is the first thing that most people seem to get wrong.

The best description I've found of the original use of MVC is actually in a presentation dated 2004 entitled "Inside Smalltalk MVC". I would guess that the canonical papers that describe the Smalltalk 80 final version of MVC are Krasner & Pope's "A Cookbook for Using the Model-View-Controller User Interface Paradigm in the Smalltalk-80" and Steve Burbeck's "Applications Programming in Smalltalk-80: How to use Model-View-Controller (MVC)". Both papers are well worth the read.

If you have some time to kill and don't mind listening to Robert Martin, he did a good keynote at Ruby Midwest 2011 that touched on MVC. It is a little over an hour, but quite entertaining and enlightening. I tend to follow with his opinion that most implementations get MVC wrong. I spent a little time looking around and finally found a diagram that I can link to which describes MVC. The one that I like came from Pope and Krasner.

MVC http://www.as3dp.com/wp-content/uploads/2010/02/mvc_pope_krasner.png

From my point of view, the following are the key points:

  • a model instance is responsible for notifying the interested objects of changes. Note that these can be any object instances. The diagram shows both views and controllers receiving updates here.
  • views are responsible for querying the current state and displaying the results. They usually perform filtering or data transformation as well.
  • controllers are responsible for accepting user input and forwarding view messages along to the view.
    • View messages are a common theme in MVC. It is important that these are independent of the UI world - these are not mouse clicks and what not but a view-specific language of events. This brings us to the next point.
  • The view does not depend on the controller in any way. Controller's are responsible for arranging and creating views and providing the interface between the rest of the world and the view.
  • In a perfect world, the view is responsible for making the model representation visible. This is how it worked when MVC was applied to desktop applications.

The reality is that MVC has been twisted and rewritten for the web world. It's not really MVC anymore or maybe MVC was simply redefined. This is why you are seeing so many different opinions and representations of MVC out there. If you are looking into writing desktop style applications, then look at the stuff by Krasner & Pope. If you are looking into how MVC is applied to the web, then I recommend Uncle Bob's keynote for an alternative that it better suited for web applications - what he called the Interactor, Entity, Boundary Architecture for lack of a better name. Dig around for stuff associated with his talks about "the Lost Years of Architecture".