理解MVC:模型上的“胖”概念是什么,控制器上的“瘦”是什么?

时间:2010-06-24 12:03:07

标签: php model-view-controller paradigms

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

问:关于MVC范例,它说Fat模型,瘦的控制器。我在这里想,如果我有很多方法(在控制器上)只使用一些抽象方法到CRUD(在模型上),我是在创建一个胖控制器而不是模型?或者他们说,胖模型,在返回和不打字的内容中进行补偿?这是我从未理解的东西=)任何评论都表示赞赏!非常感谢

OBS1:我没有在模型中做什么,在控制器中,我只有控制最新模型的方法

OBS2:让我们说“checkIfEmailExists()”,将“john@hotmail.com”作为参数。这个方法将从模型方法返回,如果这个param存在于表中,则返回boolean。如果是0,“checkIFemailExists()”将调用一个不同的模型方法,这个,他只是另一个抽象方法,执行更新操作。

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

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

Q2:还有一个问题,所以,让我说我有一个查看表单,从那里发送该电子邮件地址参数。你是说视图直接转向模型吗?

问题3:控制器不应该在他们之间行动吗?这就是范例

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

感谢您的关注

5 个答案:

答案 0 :(得分: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的回答。

答案 1 :(得分:8)

我一直在使用MVC范例,我可以与你分享我的经验。

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

“控制器”部分负责处理特定于Web的内容,例如身份验证,Cookie,GET和POST,查询字符串等。它使用模型和/或BLL中存在的内容并发送具有的数据要向用户呈现视图。

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

希望这清除了你的一些疑虑。

答案 2 :(得分:3)

我总是认为这意味着模型应该以更加面向对象的方式封装与这些模型相关的逻辑,而不是以更加程序化的方式将控制器中的所有逻辑都包含在内。引用The Cathedral and the Bazaar

  

智能数据结构和哑代码比其他方式更好。

答案 3 :(得分:2)

我可能正在展示我的偏见(对C#)但我认为除非你使用面向对象的编程风格,否则谈论MVC并不是很有意义。控制器不是方法,它是分组到类中的方法的集合,每个方法处理一些输入(url / request)。模型不是访问数据库(数据访问层)的一种方式,它是一个属性和方法的集合,它们将一些可识别的实体封装在您的应用程序中:人,预订,产品等。最好的方法想想控制器处理输入,模型包含数据 - 当然,这是简化的。

对我而言,“胖”与“瘦”的问题是你的商业逻辑在哪里生活的问题。如果你的控制器中有很多逻辑相关,不是简单地处理输入,而是实现业务逻辑,那么你的控制器比你只是简单地使用它们将请求转换为传递给视图的模型的集合来渲染相对更胖。 。根据我的经验,它并不总是一个或两个决定。很多时候,当您在控制器中具有应用程序逻辑(权限验证,清理等)时,您在模型中拥有业务逻辑(验证,关系维护,审计)。

答案 4 :(得分:0)

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

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

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