Fat models and skinny controllers sounds like creating God models
It might not be the best idea to look at Rails as a staple of MVC design pattern. Said framework was made with some inherent shortcomings (I kinda elaborated on it in a different post) and the community only just now has begun addressing the fallout. You could look at DataMapper2 development as the first major step.
Some theory
People giving that advice seem to be afflicted by a quite common misconception. So let me begin by clearing it up: Model, in modern MVC design pattern, is NOT a class or object. Model is a layer.
The core idea behind MVC pattern is Separation of Concerns and the first step in it is the division between presentation layer and model layers. Just like the presentation layer breaks down into controllers (instances, responsible for dealing with user input), views (instances, responsible for UI logic) and templates/layouts, so does the model layer.
The major parts that the model layer consists of are:
-
Domain Objects
Also known as domain entities, business objects, or model objects (I dislike that latter name because it just adds to the confusion). These structures are what people usually mistakenly call "models". They are responsible for containing business rules (all the math and validation for specific unit of domain logic).
-
Storage Abstractions:
Usually implemented using data mapper pattern (do not confuse with ORMs, which have abused this name). These instances usually are tasked with information storage-from and retrieval-into the domain objects. Each domain object can have several mappers, just like there are several forms of storage (DB, cache, session, cookies, /dev/null).
-
Services:
Structures responsible for application logic (that is, interaction between domain objects and interaction between domain objects and storage abstractions). They should act like the "interface" through which the presentation layer interacts with the model layer. This is usually what in Rails-like code ends up in the controllers.
There are also several structures that might be in the spaces between these groups: DAOs, units of work and repositories.
Oh ... and when we talk (in context of web) about a user that interacts with MVC application, it is not a human being. The "user" is actually your web browser.
So what about deities?
Instead of having some scary and monolithic model to work with, controllers should interact with services. You pass data from user input to a specific service (for example MailService
or RecognitionService
). This way the controller changes the state of model layer, but it is done by using a clear API and without messing with internal structures (which would cause a leaky abstraction).
Such changes can either cause some immediate reaction, or only affect the data that the view instance requests from model layer, or both.
Each service can interact with any number (though, it's usually only a handful) of domain object and storage abstractions. For example, the RecogitionService
could not care less about storage abstractions for the articles.
Closing notes
This way you get an application that can be unit-tested at any level, has low coupling (if correctly implemented) and has clearly understandable architecture.
Though, keep in mind: MVC is not meant for small applications. If you are writing a guestbook page using MVC pattern, you are doing it wrong. This pattern is meant for enforcing law and order on large scale applications.
For people who are using PHP as primary language, this post might be relevant. It's a bit longer description of the model layer with a few snippets of code.
If the "model" classes are implemented poorly yes, your concern is relevant. A model class shouldnt be doing Email (infrastructure tasks).
The real question is what does model in MVC imply. It isnt restricted to POCO classes with a few methods. Model in MVC means Data and Business logic. Treat it as a superset of classic core POCO models.
View ==== Controller ==== Model ---> Business Process layer --> Core models
Throw in Infrastructure assemblies and Data Access layers and use injection to hand that into the BPL then your a process is using MVC as intended.
BPL may invoke UoW / Respository patterns, and execute business rules and call Infrastructure features by way of injected Objects or interface patters.
So the recommendation to keep a controller skinny doesnt mean the "person" class in a classic Core model should have 50 methods, and call Email directly. You are right to think this is wrong.
The Controller May still be required to instantiate and inject Infrastructure classes into the BPL or core layer if called directly. There should be a business layer or at least classes orchestrating calls across Classic Object model classes. Well thats my "view" anyway ;-)
For generic take on MVC the wiki description http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
A Little Blog that talks about the "M" in MVC. http://www.thedeveloperday.com/skinny-controllers/