Jorge Manrubia

February 13, 2022

No silver buckets

olav-ahrens-rotne-4Ennrbj1svk-unsplash.jpg


The suggestion that mixing buckets is the root of all your software quality problems is common in our industry.

In Rails, it's a recurring theme from his critics. Augment Ruby core classes with monkey-patching? Wrong! Those buckets are meant to remain separate. Invoke models logic from controllers? Wrong again! Those actions deserve their own bucket. Mixing persistence and domain logic in Active Record? Sacrilege! Persistence is an orthogonal concern that should be confined to its own bucket.

I always read these critics intrigued about the premise, which looks promising. Coupling and cohesion are essential software quality traits, no question about that. But, after checking the proposed alternatives, they often look not only worse than what they confront to me, but ultimately very naive when presenting their advantages.

Let me elaborate on a concrete example: the need for a layer of "actions" that decouples controllers and models. Check this (currently retired) proposal from Shopify's Upgrow (which I wrote some thoughts about), or what Hanami proposes.

It addresses a real problem: controllers doing too much. Fat controller actions suggest your domain logic is spread across objects that have nothing to do with your domain. That isn't good. Now, I don't see how extracting those fat actions into their own entities presents a solution to the problem. What you need is something way harder to define, capture and transmit: a well-designed system exposing a clear API to be exercised from the controller. Depending of your preferences and style, that API could be an action object, a service, or a method in a model, but the determining quality factor will be how everything is designed.

In other words, if you struggle to write good controller actions, you will struggle to create good action objects.  The pattern itself doesn't get you closer to the finish line. To me, systematically creating an action object for every HTTP endpoint doesn't mean much architecturally speaking, either good or bad, other than you will now have an additional file to manage. Maybe such harness helps to enforce conventions across large teams, or perhaps it just matches your aesthetics preferences (which is a perfectly valid reason). What I don't buy is that it represents a qualitative jump forward in terms of design quality, which is exactly how this pattern is often presented.

Software design is a complex matter, and I think this is why axiomatic advice about where to place code is so appealing: it is simple. I believe personal preferences matter a lot, and every developer should go with the style that suits best. But I often see articles that present merely personal preferences disguised as software design facts, which can be misleading, especially for inexperienced readers.


---
jorgemanrubia.com
The title of this article is a humble tribute to the seminal No Silver Bullet.
Photo by Olav Ahrens Røtne on Unsplash






About Jorge Manrubia

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

jorgemanrubia.com