-
17
Jan
The principle of fat models and skinny controllers is one that I first learned when I was initiated into the Rails community about a year and a half ago. Every single one of my fellow developers repeated it, almost like a mantra. The only problem was that no one seemed to be able to articulate the why of it. Don’t get me wrong, I think they knew; I just think that they had lived with it so long that the reasons had become an afterthought.
Being the curious sort, I needed to know the why of it. Not understanding the reasons behind the thing made it difficult for me to adopt it. I would fill the controller and view with logic, telling myself the whole time that once I had it working I could clean it up and move it into the model. I’m sure a lot of you are shaking your heads as you read this, because you know what I’m going to say next. That ever elusive “clean up” session never happened. The obvious result being that my code was functional, but ugly. I was fast up front, but when it came time to make changes, things would slow down quite a bit. Especially if I wasn’t the developer assigned to make the change.
There are a lot of good articles out there about maintainability and the like. Ultimately, though, it’s about a lot more than that. Skinny controllers and fat models, as a principle, is the glue that holds pretty much all of the good coding practices together.
- TDD: Controllers are a pain in the ass to test. Ideally, all you want to have to test in controllers is that the right template is being rendered, the right action is being taken. The minute you have to start testing assignation of values, etc… That’s the minute you stop wanting to test at all.
- DRY: It’s a lot easier to spot duplicate code if it’s all in the same place, and with fat models that’s much more likely to be the case. Also, if a function you need is sitting at the bottom of some controller, it starts to get a lot easier to just copy and paste it, rather than trying to share it.
- Maintainability: The previous 2 points kind of play into this one. If you have good test coverage, and don’t have to worry so much about changes having unforeseen (and untraceable) effects in other parts of your app, you’ll be a lot less hesitant about refactoring your code. If your code is DRY, you won’t have to worry so much that the change you make here, might not show up there.
- Readability: Let’s face it, the code that’s easiest to read, isn’t DRY. It’s linear, it’s all in one place, it doesn’t make function calls that you have to hunt down (”Is that function in the helper? No, I think it’s in a lib file. No, wait, maybe it’s in this included module…”). The problem is, that this code also isn’t maintainable at all. With the kind of setup I just described, one little text change is likely to require a dozen different files to be altered. So, short of that kind of readability, you want to have everything be easily locatable. Sure, an IDE can help with that, but for those of us using TextMate and vim, we have to resort to keeping things as concise as possible. And DRY does help with that. As does keeping as much of the logic in the model (i.e. in one place) as possible.
- Design: Skinny controllers and fat models… You know what’s left out of that equation? The views. One of the nice side effects of keeping as much logic as possible in the model is that it also stays out of the view. Once you start filling the controller with unnecessary code, it’s really easy to start doing a bunch of if and case statements in the view. (”Oh, and we need this record, too, but only in this one little spot that may not even be rendered… I’ll just put the Class.find here at the top of the partial.” And so it goes.) The more you can keep code out of your view, the easier it will be for your designer to go in and integrate his or her newly chopped comp.
All of it is made easier by sticking to the skinny controller/fat model ideal. And, conversely, all of it is a lot easier to allow to fall by the wayside if you don’t.
Of course, I realize I’m not really saying anything new here, or maybe I’m just not saying anything that most rails developers don’t already know. But sometimes it helps to say it out loud, even if you’re repeating yourself.
none