【问题标题】:What, specifically, belongs in a Model, a View, and a Controller?具体来说,什么属于模型、视图和控制器?
【发布时间】:2010-08-23 12:59:03
【问题描述】:

我一直在学习模型-视图-控制器范式(“MVC”),但我很困惑,因为有些教程与其他教程相矛盾。

我目前对流程的理解是这样的:

路由器/调度程序/前端控制器:

  • 虽然在“MVC”名称中没有特别提及,但Router仍然是一个非常重要的部分。正是在这里,请求从原始 URL 转换为特定的控制器。例如,将 www.StackUnderflow.com/question/123 的请求路由到应用程序的“问题”控制器

型号:

  • 这是从某些存储源(例如数据库或 XML 文件)收集原始数据的地方。该模型充当抽象层,将控制器对特定数据的请求转换为(例如)SQL 查询,并将查询结果转换为数据对象等标准格式。

  • 例如,在上述 /browse/all 场景中:

    • “问题”控制器会询问模型“请提供问题 123 的数据。”
    • 然后模型会将其转换为“SELECT * FROM Questions WHERE Id = 123;”并将其放到数据库中
    • 数据库将向模型返回一个“问题”记录
    • 模型将获取记录,并将其转换为问题数据对象
    • 然后模型询问做同样的事情“SELECT * FROM Answers WHERE QuestionID = 123;”并从结果集中创建一个 Answer 对象数组,并将其添加到 Question 对象的 answers 成员变量中。
    • 模型会将问题对象返回给“问题”控制器

控制器:

  • 这是应用程序的真正主力。除了将消息来回中继到 ModelView 之外,Controller 还负责诸如授权 和应用程序之类的事情/“业务”逻辑编辑:根据答案,业务逻辑属于模型。

  • 在正在进行的示例中,控制器将负责:

    • 确保用户已登录。
    • 根据 URL 确定 QuestionId。
    • 确定要使用的视图。
    • 发送 HTTP 代码并在需要时重定向。
    • Model 请求数据,并将所需数据存储在成员变量中。

查看:

  • 总的来说,视图是应用程序中最简单的部分。在基本应用程序中,它主要由 HTML 模板组成。这些模板将具有占位符,可以将来自 Controller 的成员变量的数据插入到模板中:

例如

<html>

  <head>
    <title>
      <?php $question->getTitle() ?>
    </title>
  </head>

  <body>
    <h1> <?php $question->getQuestionText(); ?> </h1>
    <h2> Answers: </h2>
    <div class="answerList"> 
      <?php formatAnswerList($question->getAnswers()); ?> 
    </div>
  </body>

</html>
  • 视图还包含格式化数据以交付给用户的方法。例如,上面的 formatAnswerList() 方法会从 Controller 中获取一系列答案,并在调用类似 include $markupPath . "/formatAnswer.inc" 的东西时循环遍历它们,这将是一个仅包含答案容器的小模板.

问题:

  • 这种 MVC 观点是否从根本上准确?
  • 如果不是,请仔细说明哪些组件放错了位置,它们实际应该放在哪里,以及它们应该如何与其他组件正确交互(如果有的话)。
  • 用多少类来描述这个?在我的示例中,有四个对象——一个用于 MVC 的三个组件,一个用于简单地存储相关数据以供传输。这是正常的,还是应该结合一些。如果有,是哪些?

【问题讨论】:

    标签: model-view-controller design-patterns application-design


    【解决方案1】:

    我认为这种描述对控制器的影响太大,而对模型的影响又不够。该模型是业务逻辑所在的理想位置。控制器实际上只是站点用户的一个接口,路由控制它需要去哪里。看看之前关于该主题的讨论:

    Understanding MVC: Whats the concept of "Fat" on models, "Skinny" on controllers?

    【讨论】:

    • 我想我明白你的意图了。我在Controller中拥有的很多东西实际上是Model的一部分,而我在Model中拥有的抽象层可能更像是一个单独的实体(可能被认为是Model的子集)而不是Model的目的,是对吗?您能否更新您的答案以指定我的控制器的哪些部分应该保留,哪些应该进入模型?此外,M、V 和 C 应该都是单独的类,还是应该以某种方式组合。如果是这样,哪些部分构成哪些类?谢谢。
    • 老实说,你的例子已经很好了。我主要是在评论控制器上的“主力”评论。它可能是 UI 的主力,虽然在视图逻辑中可以做很多事情,但模型是域的主力。在另一个答案中,需要注意的关键是问题实体(您称之为记录)和问题 DTO(您称之为对象)是分开的。一个应该可以修改而不影响另一个。
    • @David:我在阅读 Giles 的回答时意识到,我可能对课程感到困惑,尽管我认为可以从上下文中推断出我的意思。就“问题”对象而言,我在示例中看到了四个。 QuestionM(模型)、QuestionV(视图)、QuestionC(控制器)和主要用于封装数据的普通旧问题——我想它可以很容易地成为一个数组而不是一个对象。
    • @David:更重要的是,有没有我在 Controller 中使用的示例不属于那里?我认为那里的一切都局限于描述状态(据我了解,QuestionC 也负责记忆状态)或将信息传递到视图或模型/从视图或模型传递信息。 HTTP 代码部分(或者实际上与 HTML 相关的任何内容,例如元标记、关键字或页面标题)是否应该成为视图的一部分,或者它们在控制器中是否合适?使用的示例非常面向 CRUD,我不想混淆:所以您是说所有繁重的工作都是模型?
    • @AgentConundrum:不,我认为问题中的控制器示例非常准确。自然地,尽可能多的展示应该在视图中。但是总有一些与演示相关的事情需要由控制器处理,就像你给出的例子一样。对于我的站点,控制器中最常见的逻辑可能是按操作授权。根据当前的身份验证令牌,它会检查角色并允许或拒绝基于此的操作。
    【解决方案2】:

    基本上你把所有东西都放在了正确的地方。

    在您的示例中,您定义了一个 Question 类 - 这将被称为 ViewModel,只是要在 View 中使用/从 View 中检索的所有数据的容器。

    在某些情况下,我看到 ViewModel 被忽略并且模型被传递给 View - 当我第一次看教程时这让我很困惑,我不喜欢省略 ViewModel,我认为它会混淆。

    【讨论】:

    • 您的 ViewModel 是我的控制器,还是我感到困惑?我将模式视为三个不同的对象(因此我的视图引用了 $question 而不是 $self)。根据您所说的忽略 ViewModel,这是否就像没有控制器而只是让模型和视图直接相互交谈?
    • 将模型视为对象和逻辑的实际域,将视图模型视为向视图提供数据的简单 POCO DTO,将控制器视为传递信息(并处理任何不属于模型的与 UI 相关的东西,例如会话状态。
    • @David:好的,所以“ViewModel”就是你所说的用于保存数据的对象——仅用于传输/存储,模型用于处理数据,控制器用于存储数据/状态并在模型视图之间传递数据,而视图仅用于呈现 HTML?这基本上正确吗?
    • @AgentConundrum:听起来很对。模型可能会变得非常复杂。对于我的大多数站点,业务逻辑都保留在服务层之后,模型本质上只是与服务的交互。在那种情况下,它最终比我想要的更程序化,但它就是这样。
    猜你喜欢
    • 2017-02-12
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 2017-07-12
    • 2023-03-03
    • 2010-09-08
    • 2018-10-27
    相关资源
    最近更新 更多