Consider Writing Helpers Before Fattening Your Models

Obesity is a growing problem around the world, not only in for the human body but the code we write.

At some point long ago, someone told me that I should write "fat models" and "skinny controllers" in an MVC application. While there is some amount of wisdom to that approach, depending on what you're doing, I've found this saying to be a lousy pattern.

In essence, it's saying that anything directly involved with the granular data coming from your model should belong in the model code, while controllers should exist merely to receive models, tell them what to do, and pass them to a destination. Thus, a model can be expected to grow and have lots of code while controllers should remain to have very little code.

Let's say that you have a model called blogEntry, and your interface needs to display a truncated version of blogEntry.body. Someone with a fat-model mindset would add a function to the blogEntry model to compute the body attribute, sanitize and truncate it, and return the output as blogEntry.shortDescription.

This is a common thing to do in a lot of codebases, especially those that use Rails but I've witnessed this(and practiced it) in Ember apps. It sounds fine enough, but there's a big problem with it.

How do you know that you don't want to also truncate the data of other models? Are your other models also going to have their own shortDescription methods? You'll end up having a lot of duplicated code that way.

Hold on, can't you share a truncate function between your models? You can, but let's step back and think about what it is we are doing here.

Truncation is a concern of the view. Why are we sticking view-related code in the model? Models should represent data persistence. If you aren't persisting a shortDescription, then putting such code into the model is misappropriating responsibilities.

The "fat model" approach is really a symptom of the illness that is object-orientation taken to the extreme; we need to get away from this idea that objects in programming should completely map to objects in reality, and that objects in reality always fit into neat categories and hierarchies. Treating virtual objects, which are utilities, to physical objects often results in too many responsibilities to a single object. A Dog database model, for instance, probably shouldn't have a bark() method since the actual purpose of a database model isn't to handle behavior, but to persist and translate data.

I don't know about you, but I don't like scrolling through several lines of code. If the code is located where it truly belongs, and the code is well organized, that's less time you(and other developers) will spend hunting and pecking for what they are looking for.

The answer is to keep everything skinny, and the alternative to fat models is almost always to write helpers.

What's a Helper?

Whether you are building a Rails or an Ember project, a "helper" is a function or module that extracts logic out of the view, simplifying the view logic.

That's all it is, plain and simple! But here's an Ember example:

// src/ui/components/short-description/helper.js (or app/helpers/short-description.js)
import { helper } from '@ember/component/helper';

  This helper just truncates text to 25 characters. 
function shortDescription([ text ]){
  return text.substring(0, 25);
export default helper(shortDescription);

Which can be used in a template like so:

{{short-description model.description}}

Helpers are usually preferable to adding methods to objects, especially models, since they can be used for multiple contexts without the need to include shared code into different classes/prototypes.

Keep it simple, stupid.