22

我试图理解模型上的“胖”与控制器上的“瘦”的概念,从我一直在讨论的内容来看,我有以下示例(取自 freenode 讨论):

问:关于 MVC 范式,它说 Fat 模型,skinny 控制器。我在这里想,如果我有很多方法(在控制器上)只使用几个抽象方法来 CRUD(在模型上),我是在创建一个胖控制器而不是一个模型吗?或者他们说,胖模型,参考返回的内容而不是输入的内容?那是我从未理解过的东西 =) 任何意见都表示赞赏!非常感谢

OBS1:我不是按模型做的,在控制器中,我只有控制模型的方法

OBS2:假设“checkIfEmailExists()”具有“john@hotmail.com”作为参数。该方法将从查询该参数是否存在于表中的模型方法中获取返回值,返回布尔值。如果为0,“checkIFemailExists()”将调用不同的模型方法,这个,他只是另一个抽象方法,执行更新操作。

OBS3:“checkIfEmailExists()”不只是一个控制器吗?他实际上并没有执行任何 CRUD,他只是在比较值等。这让我感到困惑,因为在我的脑海中这是一个控制器:S

注意:我想这不是最好的例子,因为说“检查是否存在”,听起来像是查询我的表操作

Q2:还有一个问题,假设我有一个视图表单,该电子邮件地址参数是从哪里发送的。你是说视图直接进入模型?

Q3:控制器不应该在他们之间行动吗?这就是范式

最后注:讨论结束,说我错了,希望没问题(我正在学习)。但是,那么,Q2 和 Q3 的正确答案是什么?

感谢您的关注

4

5 回答 5

34

您的应用程序是 M。它应该能够独立于 V 和 C。V 和 C 形成您应用程序的用户界面。无论是 Web 界面还是命令行界面,对于运行应用程序的核心业务逻辑都无关紧要。您希望模型具有业务逻辑。

如果你有一个胖控制器,例如充满业务逻辑,你就没有遵守 MVC 的目的。控制器的唯一职责是处理 UI 请求并将其委托给模型。这就是为什么它应该是瘦的。它应该只包含它所负责的代码。

简化示例

public function fooAction()
{
    if(isset($_POST['bar'])) {
        $bar = Sanitizer::sanitize($_POST['bar']);
        $rows = $this->database->query('SELECT * from table');
        try {
            foreach($rows as $row) {
                $row->foo = $bar;
                $row->save();
            }
        } catch (Exception $e) {
            $this->render('errorPage');
            exit;
        }
        $this->render('successPage');
    } else {
        $this->render('fooPage');
    }
}

什么时候应该

public function fooAction()
{
    if(isset($_POST['bar'])) {
        $success = $this->tableGateway->updateFoo($_GET['bar']);
        $page    = $success ? 'successPage' : 'errorPage';
        $this->render($page);
    } else {
        $this->render('fooPage');
    }
}

因为这就是控制器需要知道的全部。它不应该更新行。它应该只是告诉模型有人要求进行此更改。更新是管理行的类的责任。此外,控制器不一定必须清理值。

至于 Q2 和 Q3,请参阅我对Can I call a Model from the View 的回答。

于 2010-06-24T12:27:10.173 回答
9

我一直在使用 MVC 范式很长一段时间,我可以与您分享我的经验。

“模型”部分负责处理并非严格意义上的“Web”的所有内容,例如验证、逻辑、数据访问等。可以将其视为一种混合的业务层 + 数据访问层。您还可以在单​​独的程序集中使用 BLL+DAL,并使用 MVC 的“模型”部分作为 BLL 和应用程序之间的桥梁,并添加特定于 MVC 应用程序且与 BLL 无关的类,例如 ViewData 类, ETC。

“控制器”部分负责处理特定于 Web 的内容,例如身份验证、cookie、GET 和 POST、查询字符串等。它使用模型和/或 BLL 中存在的内容并发送必须呈现的数据给用户的意见。

“视图”是您的 html 模板,可以从控制器接收数据并显示它。视图中不应该进行任何逻辑操作,因此没有“if”语句、没有循环等。如果您发现自己有这样的需求,那么您需要一些“帮助”方法来创建所需的 html,然后从看法。因此视图只接收数据,并提供给用户链接/表单以将数据发布到控制器,但它们没有详细说明任何内容。

希望这能消除你的一些疑虑。

于 2010-06-24T12:11:58.300 回答
3

我一直将其解释为意味着模型应该以更加面向对象的方法封装与这些模型相关的逻辑,而不是以更加程序化的方法将所有逻辑都包含在控制器中。引用大教堂和集市

智能数据结构和愚蠢的代码比其他方式工作得更好。

于 2010-06-24T12:16:40.443 回答
2

我可能会表现出我的偏见(对 C#),但我认为谈论 MVC 没有多大意义,除非您使用的是面向对象的编程风格。控制器不是方法,它是分组到一个类中的方法的集合,每个方法都处理一些输入(url/request)。模型不是访问数据库的一种方式(即数据访问层),它是一组属性和方法的集合,这些属性和方法封装了应用程序中的一些可识别实体:人、预订、产品等。想想看,控制器处理输入,模型包含数据——当然,这是简化的。

对我来说,“胖”与“瘦”的问题是你的业务逻辑在哪里的问题。如果您的控制器中有很多与控制器相关的逻辑,而不是简单地处理输入,而是实现业务逻辑,那么您的控制器比您简单地使用它们来将请求转换为模型组合并传递给视图进行渲染的情况相对更胖. 以我的经验,这并不总是一个非此即彼的决定。很多时候,模型中有业务逻辑(验证、关系维护、审计),而控制器中有应用程序逻辑(权限验证、清理等)。

于 2010-06-24T12:20:23.493 回答
0

我认为可以通过让控制器执行不涉及/很少涉及业务逻辑的“语法”相关操作并使用模型执行“语义”相关操作来实现良好的控制器/模型分离。

这种分离的一个很好的例子是:

您可以在控制器中对电子邮件执行正则表达式检查,但不会在控制器中执行该电子邮件的 ldap 匹配。

于 2010-06-24T12:17:28.587 回答