Someone has been wrong on the internet. I hate it when that happens. And so I started to write a comment and then I thought to my self, hey, this is great blog post material, why should I waste it on someone who is wrong on the internet. So here we go. It reads like a comment on someone who was wrong on the internet at times, because that’s exactly what it is :)
Today, I’ve stumbled across a blog post, via RubyFlow, which is boldly named Ruby on Pains by Facundo Spagnuolo. It is a melange of falsly applied pure OOD wisdom and (I can only assume) juvenile arrogance (Do I sould like an old fart already? I’m in my forties now, I have to sound like an old fart now), that made me a little angry and made me want to reply. Not sure this is a winning move, but I think my reply does contain some parts that bear repeating, so here we go.
I must admit, at first I got a bit angry reading the article. Not so much because of the things Facundo wrote (I’ll get back to that later) but the way he wrote it. It sounds very condescending. I’m sure it’s partly intentional, but let me tell you: It really undermines the argument and also makes him sound like an arrogant human being, which I’m sure he isn’t. One additional stylistic note: For the very clickbaity title, he seriously underdelivers on actually describing actual pains. He describes design problems all right, but a design problem is not automatically a pain. A design problem might cause pain for a development team but I think the story would have been much more convincing by telling actual stories from real life where the Rails architecture actually caused a team pain. These stories exist, as we all know.
Code that violates your own personal sense of “OO paradigm” (what ever that means) may cause you some discomfort, but calling it a pain is simply hyperbole (Maybe he’s suffering from a very seldom form of synesthesia, though. You can never know).
But I am also not sure he understood “The Rails Way” very well. He seems to be convinced that the Rails architecture is inherently bad, mostly because it is tightly coupled and ActiveRecord objects have too many responsibilities. Many people would agree from an abstract standpoint. But what many people don’t get that these are not rookie design mistakes, but deliberately chosen trade offs. All these extra classes he’s suggesting do not write themselves. They have to be written, reasoned about and tested. I’m not saying the design he proposes is bad (even though, in a pairing session, I would probably have slapped him with a wet trout for trying to use Exceptions for validation errors, but I’m not the first one to point this out, so let’s leave it at that), but it helps to think about at which point such a refactoring would be necessary.
Because, I am not arguing for never leaving “The Rails Way”. Most long living applications, at some point or another, leave the sweet spot of what “The Rails Way” is really good at. I want to argue that this probably means years or at least many months for most apps and not just “after kickoff”, but that’s semantics.
Additionally, he argues that the ecosystem (Gems as “coals”, as you’ll get your hands dirty when you touch them) is bad as well, because they keep on adding to the AR shitpile (my words). But at that point he’s conflating two completely different states a Rails app can be in: In the beginning, when your models are simple and your app is small and very “Rails way” so to speak, adding something like Kaminari or will_paginate directly to your models is not a problem. It is, again, a deliberate design choice and makes adding pagination to your web app a very straight forward process.
But: Last time I looked, both Kaminari and will_paginate have very simple to use ways of attaching them to arbitrary enumeration containers that implement the necessary API. This is obviously not true for every gem from the Rails eco system. But are you really telling me that if your App has a substantial amount of non “Rails Way” code that you are still blindly installing gems without looking for stuff that actually works with your architectural approach?
And this is what it boils down to, really: Most problems teams have with growing Rails applications are not actually technical problems. Rails does not resist the refactorings you’re suggesting. It might not be actively helpful, I agree, but at least in current versions, it does not resist. Everything else is social problems: A Product Owner who doesn’t give the team the freedom to do the necessary refactorings. An unexperienced team who was held together only by Rails’ conventions and now struggles to find a common path to a better app design. Or simply a team that ignored the slowly boiling water and now sits on top of a 5000 line User model.
But let me make one thing clear: This is not a technical problem, nor is it Rails specific. This happens everywhere. I’ve seen seasoned Java developers almost cry while trying to get rid of dependencies that kept them from just upgrading a framework dependency or swapping out components.
So please do me a favor and stop bashing Rails for it’s deliberately chosen deviations from the “pure OO” design school. People are using this wonderful framework for more than 10 years now to quickly iterate on user facing stuff without caring that much for these deviations and worry about actual architectural problems when they actually become problems. And, if they are good at their job, they then go and fix these problems, maybe by applying a bit of SOLID principles here and there until the code feels malleable enough again. To paraphrase Dave Thomas (again): Good software is software that is easy to change. Nothing else matters.
And really: Never ever think you can design real life software in a way that allows you to swap out a framework like Rails just like that. This is not how this works. This is not how any of this works.