Jorge Manrubia

March 6, 2021

Smelling Rails smells

Shopify recently published Upgrow: A sustainable architecture for Ruby on Rails. It describes a set of architectural principles to build Rails applications and announces a companion future gem.

I was surprised by seeing Shopify endorse this approach. The proposed patterns aren't new. Many people have advocated for them since Rails is Rails: extract the persistence layer from models to repositories, extract commands from controllers (actions) and use form objects (inputs), etc. While I appreciate the value in applying each "missing piece" in some circumstances, using them in all cases as the sanctioned way to program in Rails would make this not work for me. But I can't tell if this makes sense for an organization at the scale of Shopify or not. Maybe it does.

Now, the most disappointing part of the guides was the number of nonsensical affirmations introducing these principles:

This stack is a perfect fit for most features, as long as their business logic is simple and lightweight. In a real world scenario, where real people use such apps, this is never the case. 

Each "real" reads as a red flag. Is the author presenting the correct way of building "real" apps to be used in the "real" world by "real" users? 

The reason why actions are long and complex in real world apps is because they are just the most convenient place in the entire Rails stack to shelve quick changes and fixes. 

Again, "real". So, if instead of having long controller actions, you place those chunks of code in command objects, that originally messy code starts smelling like roses.

Using macros such as “has many” and “belongs to”, associations allow Active Record models to define how they are linked to one another, dynamically defining methods that return collections of associated records for a given Active Record model instance. This is a classic behaviour in Rails apps that allow writing features around nested resources very easily.

In real world production apps, however, these shortcuts are often anti-patterns that make code interdependent, complex, and slow. Active Record Associations tie models together, creating unnecessary coupling between them.

In real-world production apps™, using "has many" is an anti-pattern. I must say this is a new one to me.

I think this very same proposal presented more pragmatically would tell a different story. The "real world" narrative and the implied suggestion that good software design will follow to using predefined buckets for your code sounds so naive to me. What about: we are a lot of programmers, and some structure and ceremony helps? I could buy that.

I know Shopify is full of brilliant people and I am sure something good will come out of this, but this didn't look like a promising start to me.

About Jorge Manrubia

A programmer who writes about software development and many other topics. I work at 37signals.