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

I'm trying to understand the concept of "Fat" on models vs "skinny" on controllers and from what I've been discussing I have the following example (this is taken from a freenode discussion):

Q: On MVC paradigm, its said Fat models, skinny controllers. I'm here thinking, If I have lots of methods (on controller) that uses just a few abstract methods to CRUD (on model), am I creating a fat controller instead of a model ? Or they say, fat model, refearing in what is returned and not typed ? that's something I've never understood =) Any comments are appreciated! Thanks a lot

OBS1: I'm not doing whats ment by the model, in the controller, I just have methods that control whats going to the model

OBS2: let's say "checkIfEmailExists()", has "[email protected]", as a parameters. This method will, get the return from the model method that querys if this param exist in table, return boolean. If is 0, "checkIFemailExists()" will call a diferent model method, this one, he's just another abstract method, that performs Update operation.

OBS3: The "checkIfEmailExists()", isnt just a controller ? He's not actually performing any CRUD, he's just comparing values etc. That's whats confusing me, because in my head this is a controller :S

Notes: I guess this is not the best example, since saying "check if something exists",sounds like a query my table operation

Q2:just one more question, so, let's say I've got a view form, from where that email address parameter is sent from. Are you saying the view goes directly to the model ?

Q3:Shouldn't the controller act between them ? thats the paradigm

FINAL NOTE: The discussion ended, saying that I'm wrong, wish is ok (i'm learning). But, so, whats the right answers for Q2 and Q3 ?

Thanks for your atention


Solution 1:

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.

Solution 2:

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.

Solution 3:

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.

Solution 4:

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.