Fat models, skinny controllers and the MVC design pattern

Model View-ControllerCakephpModelController

Model View-Controller Problem Overview


I just read a blog post that explains MVC with a banking analogy. I have a few months of experience with web application development with an MVC framework (CakePHP), so I get the basics, but I began to see a theme that made me think I'm taking a flawed approach to where I put my logic:

  • Fat models, skinny controllers
  • Keep as much business logic in the models as possible

In my app, models are anorexic and controllers are obese. I have all business logic in the controllers and nothing besides associations and validation rules in the models.

Scanning through my controllers, I can now identify a lot of logic that should probably go in a model:

  • The app has lists, which contain items, and the items can be ranked. The sorting logic which puts the list in ranked order is in a controller.
  • Similarly, items (Item model) also have images (Image model). Each item may have a default image (designated by image_id in the items table). When an item is displayed with its images, the default image should appear first. I have the logic that does this in a controller.
  • When a list is displayed, related lists are displayed in the sidebar. The logic to determine which lists are related is in a controller.

Now to my questions:

  1. With the examples I gave above, am I on the right track in thinking that those are instances of logic presently in a controller that belongs in a model?
  2. What are some other areas of logic, common to web apps, that should go into models?
  3. I'm sure identifying this problem and changing my design pattern is half the battle, but even if I decide to take those examples I gave above and try to move that logic to a model, I wouldn't know where to begin. Can anyone point me in the right direction by posting some code here, or linking to some good learning resources? CakePHP specific help would be great, but I'm sure anything MVC will suffice.

Model View-Controller Solutions


Solution 1 - Model View-Controller

It's a bit tough to give you the "right" answers, since some of them deal with the specifics of the framework (regardless of the ones you are working with).

At least in terms of CakePHP:

  1. Yes

  2. Anything that deals with data or data manipulation should be in a model. In terms of CakePHP what about a simple find() method? ... If there is a chance that it will do something "special" (i.e. recall a specific set of 'condition'), which you might need elsewhere, that's a good excuse to wrap inside a model's method.

  3. Unfortunately there is never an easy answer, and refactoring of the code is a natural process. Sometimes you just wake up an go: "holy macaroni... that should be in the model!" (well maybe you don't do that, but I have :))

Solution 2 - Model View-Controller

I'm using at least these two 'tests' to check if my logic is in the right place:

  1. If I write a unittest, is is easy to only create the one 'real' object to do the test on (= the object that you are using in production) and not include lots of others, except for maybe some value objects. Needing both an actual model object and an actual controller object to do a test could be a signal you need to move functionality.

  2. Ask myself the question: what if I added another way to use these classes, would I need to duplicate functionality in a way that is nearly copy-paste? ... That's also probably a good reason to move that functionality.

also interesting: http://www.martinfowler.com/bliki/AnemicDomainModel.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionryonlifeView Question on Stackoverflow
Solution 1 - Model View-ControllervladkoView Answer on Stackoverflow
Solution 2 - Model View-ControllerSimon GroenewoltView Answer on Stackoverflow