Monday, January 30, 2012

Re: Help Understanding Fat Models

Thank you Jeremy. This is a great, concise description and the example code helps a lot to see the difference.

 {c}


On Mon, Jan 30, 2012 at 4:52 PM, jeremyharris <funeralmoss@gmail.com> wrote:
The best advice is to keep things DRY (Don't Repeat Yourself). Generally, this results in thin controllers (small controller functions) and fat models (more methods on the models). Any functionality that you will find yourself reusing across different controllers that appropriately relate to a model should be on that model, instead.

As an example (typical blog example).

//posts_controller
function edit($id) {
// check if user is the creator of this post and is therefore allowed to edit
$post = $this->Post->read(null, $id);
if (empty($post) || $post['Post']['created_by'] != $this->Auth->user('id')) {
//redirect
return;
}
}

function delete($id) {
// check if user has rights to delete
$post = $this->Post->read(null, $id);
if (empty($post) || $post['Post']['created_by'] != $this->Auth->user('id')) {
//redirect
return;
}
}

Your controller would be considered "fat" because you duplicated code and this is logic that belongs in the model. Instead, something like this looks better:

// post model
function userOwnsPost($userId, $postId) {
return $this->hasAny(array(
'id' => $postId,
'created_by' => $userId
));
}

// posts controller
function edit($id) {
if (!$this->Post->userOwnsPost($this->Auth->user('id'), $id)) {
//redirect
}
}

function delete($id) {
if (!$this->Post->userOwnsPost($this->Auth->user('id'), $id)) {
//redirect
}
}

Perhaps not the *best* example, but you get the idea. This code is also much easier to test. If you ever change the behavior of userOwnsPost, it will change across the app. It's also very specific, which makes writing tests really easy.

If you find yourself writing long, complex find conditions and using them over and over again, they probably belong in model. Remember, many small functions are easier to test and predict the outcome than large functions.

Another example might be finding a list of posts that belong to a tag. You would place this in your Post or Tag model, and might call it in /posts/index, /pages/home, /posts/view, /users/posts_in_tags_i_have_created, etc.

For small apps, it may not be necessary to move these functions around! But, I'd say the more you have in models the better, even if only for testing's sake. It's easier to find out what went wrong when your methods are smaller and very specific. Controller methods are usually less specific than model methods.

Hope that clears it up a bit.

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.
 
 
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.
 
 
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

No comments: