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

白昼怎懂夜的黑 提交于 2019-11-27 00:32:02
Gordon

Your application is the M. It should be able to stand independent from V and C. V and C form the User Interface to your application. Whether this is a web interface or a command line interface shouldn't matter for the core business logic of your application to run. You want the model to be fat with business logic.

If you have a fat controller instead, e.g. full with business logic, you are not adhering to the purpose of MVC. A controller's sole responsibility is handling and delegating UI requests to the Model. That's why it should be skinny. It should only contain code necessary for what it's responsible for.

Simplified Example

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');
    }
}

When it should be

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

because that's all the controller needs to know. It should not update the rows. It should just tell the model that someone requested this change. Updating is the responsibility of the class managing the rows. Also, the controller does not necessarily have to sanitize the value.

As for Q2 and Q3, please see my answer to Can I call a Model from the View.

I've been working with MVC paradigm for a long time and I can share with you my experience.

The "model" part is responsible of handling all the stuff that isn't strictly "web", such as validation, logic, data access, etc. Think of it as a sort of mixed business layer + data access layer. You can also have BLL+DAL in separate assemblies and use the "Model" part of MVC as a bridge between your BLL and your App, plus adding classes that are specific to the MVC app and not related to the BLL, such as ViewData classes, etc.

The "controller" part is what takes care of the web specific stuff, like authentication, cookies, GETs and POSTs, querystrings, etc. It uses the stuff present in the model and/or the BLL and sends the data that has to be rendered to the user to the views.

The "views" are your html templates that can receive data from the controller, and display it. No logic operations should ever be done in the views, so no "if" statements, no loops, etc. If you find yourself having such needs, then you need some "helper" methods that create the desired html and then call them from the view. So views only receive data, and offer to the user links/forms to post the data to a controller, but they don't elaborate anything.

Hope this cleared some of your doubts.

I've always interpreted that to mean that the models should encapsulate logic related to those models in a more object-oriented approach, as opposed to having all the logic in the controllers in a more procedural approach. To quote The Cathedral and the Bazaar:

Smart data structures and dumb code works a lot better than the other way around.

I may be showing my bias (towards C#) but I don't think it makes much sense to talk about MVC unless you're using an object-oriented programming style. A controller isn't a method, it's a collection of methods grouped into a class, each of which handles some input (url/request). A model isn't a way of accessing the database (that's a data access layer), it's a collection of properties and methods that encapsulate some identifiable entity in your application: a person, a reservation, a product, etc. The best way to think about it is that controllers handle input, models contain data -- but, of course, that's simplified.

The question of "Fat" vs "Skinny", to me, is the question of where does your business logic live. If you have lots of logic in your controller related, not to simply handling input, but implementing business logic, then your controller's are relatively fatter than if you simply use them to translate requests into assemblages of models that are handed off to a view to render. In my experience, it's not always an either/or decision. A lot of the time you have business logic (validation, relationship maintenance, auditing) in the model while you have application logic (permission validation, sanitization, etc.) in the controller, too.

I think a good controller/model separation could be made by letting controller do "syntactic" dependent operations with no/few business logic involved and use model to perform "semantic" related operations.

A good example of that separation is:

you may perform regexp check of an email in controller but you won't perform ldap matching of that email in controller.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!