Solid design for Rails applications
This is a preview of my upcoming presentation at the Italian Ruby Day, in Milano on June 10.
Kent Beck wrote in Smalltalk Best Practice Patterns:
There are a few things I look for that are good predictors of whether a project is in good shape. These are also properties I strive for in my code.
Once and only once – If I only have one minute to describe good style, I reduce it to a simple rule: in a program written with good style everything is said once and only once. This isn’t much help in creating good code, but it’s a darned good analytic tool. If I see several methods with the same logic, or several objects with the same methods, or several systems with similar objects, I know this rule isn’t satisfied. This leads us to the second property:
Lots of little pieces – Good code invariably has small methods and small objects. Only by factoring the system into many small pieces of state and function can you hope to satisfy the “once and only once” rule. I get lots of resistance to this idea, especially from experienced developers, but no one thing I do to systems provides as much help as breaking it into more pieces. When you are doing this, however, you must always be certain that you communicate the big picture effectively. Otherwise, you’ll find yourself in a big bowl of “Pasta a la Smalltalk”, which is every bit as nasty a dish as “Fettucine a la C”.
Replacing objects – Good style leads to easily replaceable objects. In a really good system, every time the user says “I want to do this radically different thing,” the developer says, “Oh, I’ll have to make a new kind of X and plug it in.” When you can extend a system solely by adding new objects without modifying any existing objects, then you have a system that is flexible and cheap to maintain. You can’t do this if you don’t have lots of little pieces.
…
I like this description of Kent’s. I think this explains well something important, that many people miss when they start doing Agile programming. (That includes me :-) The original XP books somehow imply that the reader agrees with the above. That’s because these principles are a key to write code that’s easy to change.
“Lots of little pieces” and “Replacing objects” are particularly interesting. They agree with the Open-Closed Principle. They mean that the code should grow preferably by generating new objects, not by adding code to existing objects. (See also this post by Michael Feathers.)
Now take a look at Rails applications. How do they fare with respect to the above principles? Now, Once-and-only-once has always been a Rails battle cry. But what about “Lots of little pieces”? With Rails, everything is centered around database tables. You can reconstruct the logic of a Rails application by starting with the Entity-Relationship model. For every entity you have a Model class, then probably a Controller class, its Helper module, and a number of Views. In most cases, the Model and Controller classes will be modified all the time during the evolution of the application. This is in contrast to the Open-Closed Principle. In other words, it’s not obvious how to express a Rails model as a composition of simpler objects that are reused across the application.
There are (relatively) well-known Rails techniques for reducing the size of controllers. But the consensus advice of aiming for skinny controllers, fat model leaves us with the problem of the fat models. There is no obvious, well known technique for solving this problem systematically.
In my presentation at Ruby Day I will suggest a few ways you could deal with this problem. I will talk about the main techniques for breaking up things in small pieces at the view, controller and model level. I don’t claim I have *the* solution; I have a few ideas that work. Some are from the Rails Antipatterns book, some are from my own experience working with Rails. Some are a bit unconventional :-)