Recovering from “Fat Model, Skinny Controller”

Like many programmers, I’ve had a long, tortured journey through the world of software design as I did what worked in the moment and only later discovered the consequences of my decisions. I was especially “lucky” in this respect as my first professional software job was as the sole architect of what became two 20k+ line Rails applications.

I was a full six months into this job when the clouds parted and I heard the “Fat Model, Skinny Controller” axiom. In the back of my head, I’d been asking myself what exactly the purpose of Models even were. Each of my models had associations, a few scopes, some simple validations, and some data accessor methods. My controllers on the other hand were beginning to collapse under their own weight as I added more and more complex business logic to them.

When “Fat Model, Skinny Controller” entered my life, the MVC architecture started to make so much more sense. Rather than cramming all that logic into a forest of imperative steps and deeply nested branching logic, I could pull most of it out into smaller testable chunks.

And so I dove headlong into the world of Fat Models. Corpulent butterballs of vaguely related functionality. User#assign_password, User#reimburse, User#send_thank_you_note_for_tolerating_buggy_software!, throw it all in! It was easier to test, yes, but I’d only delayed the tipping point of un-maintainability by a year or two.

I was never actually able to dig myself out from under that codebase. Eventually the market convinced us it really actually for real wasn’t interested and I shopped around for another company, one with experienced programmers who could teach me how to build applications the right way the first time around.

Fortunately for me, thats not quite what happened. I did find a great company with some engineers that had a lot of energy for thinking about software design. The lucky part is that that sensibility was actually pretty new. There was a lot of misplaced logic, a lot of good-enough-just-ship-it design, and most of all a complete and total devotion to the Rails Model. I count this as lucky because while following exemplary code may be easier than making incremental improvements to the design of a codebase that has deeply entrenched anti-patterns, I still had a lot of unresolved cognitive dissonance from my previous projects that would go unresolved if I was simply fed an easier way.

And now, 6 years into my career building software, the ultimate irony is that I’ve returned to my naive understanding of what belongs in a Rails Model: associations, scopes, some simple validations, and some data accessor methods. Thats plenty. More than enough for one class, actually.

My goal is to write an abstract implementation of the business logic and only use frameworks like Rails to handle the implementation of non-application-specific concerns like persistence and HTTP access.

Starting out, I had no idea what the lib/ directory could possibly be used for, but thats now where almost all my business logic goes. My goal is to write an abstract implementation of the business logic and only use frameworks like Rails to handle the implementation of non-application-specific concerns like persistence and HTTP access. Back then I had no real idea why you would create a class without a database table behind it (maybe because there was no rails generate script for doing so /s). If I had a Model with a really complex validation scheme I would just let my validations grow and grow, never thinking to create a class with validation as its single responsibility. When I had a requirement that involved data from multiple Models, I would simply pick the Model that seemed to have the biggest share of the functionality and let it handle everything (“Hmm, should it be Item#purchase, User#purchase, or Invoice#purchase?”). Life free from the bondage of the Rails Model is so much easier now (Why not just Purchase#new from lib/purchase.rb or even lib/economy/purchase.rb?).

I feel immensely grateful for having had so much time to see the effects of bad design in the applications I’ve worked on, and having seen the productivity gains that follow ambitious refactorings. Its also one of the reasons I don’t like the tendency this industry seems to have of encouraging especially young engineers to change jobs every year. When I made the mistake of bloating my Models, it wasn’t because I hadn’t read a score of blogs and books that encouraged to me to do otherwise. It was because I hadn’t yet felt the pain of poor design that seemed easier in the short run.

2 thoughts on “Recovering from “Fat Model, Skinny Controller”

  1. “It was because I hadn’t yet felt the pain of poor design that seemed easier in the short run.”

    This also describes my experience. The first system I naively built became difficult to maintain only after it had grown large enough for me to not be able to hold the whole thing in my head at once. Up to that tipping point the design didn’t matter as much because it worked.

Leave a Reply

Your email address will not be published. Required fields are marked *