September 28, 2017
A couple of months back, I finished my first major project with Ruby but sans Rails. You probably don’t know that, but I’m one of these people who first try to master a framework and only then look at the language documentation. This is the approach taught by “the Rails way.” When I started my adventure with Rails, I believed it to be a perfect framework, God’s gift to developers. A couple of months later, I saw big, old RoR projects… and I wanted nothing more than to run away from Ruby as far away as possible.
But wait a minute—why would I run away from Ruby if I hated Rails? Well, because for me it was all the same. Around that time, a colleague “invited” me to participate in their project which used a library I hadn't heard of before—Ruby Object Mapper. It was a breakthrough moment for me, because it allowed me to see new possibilities beyond Rails. I started taking a greater interest in writing applications that were better, more aware, and used a range of other libraries. Then, I decided to write an account of these adventures and draw some conclusions that wouldn't be invalidated by the passage of time.
Rails Isn't Bad; It’s Just That Developers Use It Wrong
Ruby on Rails is a framework like any other. Simple to use and with a huge community to boot. It’s a perfect tool, especially in the api_only “version.” It has specific purposes in applications with uncomplicated domains, in prototypes and blogs, sometimes in bigger projects too. In the latter case, we often have to deal with the issue of adapting architecture to the real complexity of the domain. But why do so many developers use popular as a substitute of universal? Why was RoR treated like a “unicorn” framework? In my personal opinion, Rails gained notoriety because it was misused in the wrong places.
If something supposedly fits everything, there is a considerable possibility that it doesn’t actually fit anything. Each case needs to be analyzed separately, and in edge cases, one should consider switching to a different technology stack.
Compare it, for a second, to what contemporary medical practice looks like—although in theory primary care physicians are equipped to diagnose the overwhelming majority of diseases they come across, it doesn’t necessarily mean that they design the course of the treatment. So don’t try that approach in software development, it doesn’t work here either.
Rails Isn't Bad; It Makes Developers Lazy
Everyone who has ever tried to develop an application using Sinatra is probably perfectly aware of what I’m trying to say. Only then the developer is able to understand what’s happening under the syntactical sugar. When we try to create everything from the low level up, we often end up seeing how little we know about the application functioning. That, however, is the most valuable knowledge—to quote Socrates, “Scio me nihil scire.”
Rails has this saying, “If you have a problem, first look for the gem that solves it.” Looks awesome when we write a prototype, but is it still valid for the conscious developer? No, unfortunately not. Overusing gems and pre-made solutions kills creativity, but, what’s even worse, it affects the possibility of expanding the project. Obviously, that’s not a given, but it’s essential to strike the proper balance—if we’re aware of how gems affect our app and what they mean for the future of our application, then that’s OK. You need to remember, however, that any additional gems always impose specific limitations on us and on our projects (at least their business side). We often end up never reaching or crashing against these restrictions, but I can easily imagine a situation where we encounter a blocker related to a gem we added barely a week ago. But how can we establish where that particular line runs? Well, it's actually very difficult to do that. This is the reason why deep analysis of particular requirements and additional information is so relevant. It hehlps us understand how a given feature depends on a domain and whether there are any specific edge cases to consider. If you find even one small bad omen in the process, you better find your own implementation. Trust me. The more people learn that “dating a framework is better than marrying it (credit: Uncle Bob),” the better off our abilities will be.
Given my experience, I suggest a couple of simple steps that anyone can follow should they encounter a difficult issue in our domain (not in the framework!):
How can we understand how a library works if it has no documentation? Source code and tests. In perfect world, we could probably infer everything about the tool from these two things. Naturally, such an approach requires extensive abilities and time, but it also allows the developer grasp a given library or framework much, much faster. You may think that this is an exaggeration, but I believe that everyone who at least tries that approach will almost immediately understand what I mean.
Using this method, you not only learn how to use a framework, you learn better coding, testing, describing, and documenting source code, and, most importantly, you get to read the code as if there was a manual! Personally, I don’t remember the last time I looked for something in the docs. Usually, I simply jump straight to the repository.
This particular approach is sort of extreme and looking at the matter from the opposite side is always healthy. So—documentation is also a great source of knowledge. But wait—there’s more! Usually, documentation is the first thing that the developers looks through when they start their adventure with this framework or another. I don’t really believe that a world without documentation would be better, I actually think that’s utter nonsense. Given my own experience, I tend to think that great documentation is a considerable boon, as when I started my adventure with ROM, the available documentation covered barely a couple of percent of the entire toolkit. Most of the time I dedicated to learning its ins and outs was spent on testing what I should do next, because very little was explained in the resources available to me. It was an incredibly time-consuming process and I remember it as a terrible inconvenience. Rails, on the other hand, boasts perfect documentation and even users completely new to the framework could easily find whatever information they were looking for, usually in one place.
Keep in mind, however, that our skills grow directly in proportion to the code we’re able to understand, not the documentation! :)
And remember one more thing—you should always aim for balance. When we have time, we can try to stay focused on educating ourselves, but most of the time we need to act fast and then our "learning from code" process needs to take a back seat.
Well, I’d argue that it is a solution suitable for problems with some complexity and a quite narrow domain. Would I go with Rails if I were starting a new project now? Well, I already do, without regret, but as I mentioned before—the most important thing is to choose the right tool for the problem, not the other way around. Do we need a huge forging hammer when all we want to do is stick a nail into a wall? On the other hand, however, driving a nail into a wall requires a tool, you can’t do it with your hands alone. It’s not the speed with which we write functionalities that makes us good programmers, but rather the ability to make the right decisions depending on the circumstances.
In my next piece, I will be laying down my thoughts on the Rails Way and Active Record, so stay tuned!