Thanks!
Thanks!
Let me unpack that claim.
In the models-and-controllers view of the world, there’s no obviously good place to represent the relationships between models. The relationship logic usually ends up getting stuffed into controllers (making them “fat”) or into arbitrarily designated models (making them “chubby”). For a long time now, though, everyone has been told to keep their controllers “skinny,” so now most of this logic ends up in models. And so we get a lot of “chubby” models these days.
Example time.
Say you have employees, who have roles at companies, which own assets. You’ll have a model class for each of these real-world concepts: Employee, Role, Company, Asset. So far, so good.
Now say you need a way to determine whether a given employee should be allowed to sell a given asset. Well, the answer to that question depends on the role that the employee has at the company that owns the asset. So where do you put the logic that answers the question?
Some people would put it in the Employee class, so they can write employee.can_sell?(asset). Others would put it on the Asset class, so they can write asset.sellable_by?(employee). Others would mix it into controller logic somewhere, because that’s where the employee and asset objects interact. And yet others would create a separate module of permissions logic to house the interaction, so they can write permissions.has_sell_on?(employee, asset).
If you choose to put that kind of relationship logic into a model class, and lots of people do, odds are you’ll make the same decision again and again. And, in time, your models will get “chubby.”
The problem is that, after a while, your models get bloated up with logic about other models and become harder to reason about.
In this context, DHH is pointing out that rather than duplicating the code for tagging and the code for managing visibility and the code for managing a Dropbox account on each class that needs these things you can use a Concern to abstract out each of those groups of functionality and then apply them case-by-case with one line of code. It's a pretty neat trick and used appropriately it looks like it would really help keep the model layer trimmed down to its bare essentials.
Thanks.
Less code? Yes. Cleaner code? Yes. Faster? Probably not detectably faster or slower.
It's not a problem for the computer if you have a lot of code in a single file, but it is a problem for the computer programmer. If there's a lot of functionality in a single file, class, or other grouping of code, that makes it much more difficult for a human to understand and remember the details.
It's easier to work with a project if you can break it down into small pieces that are each individually easy to understand, so a goal of good project organization is to make your code out of small parts - small files, small models, a small number of lines of code - and have the parts be easy to distinguish and remember.
If you split one big "User" model into separate bits for billing, authorization, and user settings, not only is it easier to understand what parts there are, when you need to go in and make a change to the billing code, you immediately know that 2 out of 3 of the pieces can be safely ignored.
Similarly, if you take some very common functionality that models often have and generalize it, you only need to learn the general version once and then it applies to each of the parts. That's what the article describes. Many models are "Searchable" or "Taggable", but you only need to learn how searching or tagging works once, and the same search or tag code applies in multiple places.
Thanks.