It is going to be a rant. But a nice one. A piece of consideration from a desperate cult member that wants to make his beloved language better, that wants its worshippers to get away from the choking grip of the cult and become freer, more diverse in their thoughts, less ignorant to the problems of the ecosystem surrounding them.
My first commercial experience that counts happened to be with Rails. I’ve started working with the framework when I entered a boot camp in one of the small companies in my hometown. I was a late sophomore, smart but not really diligent. I knew some C++ programming, a bit of Python and Java, but every attempt to get started with actual application development of something harder than simple hello world blog was failing due to various reasons. Sometimes my motivation was simply gone after a few days of fighting with compilation errors and wrong test outputs, at other times I was starting a project just to throw it away after a few days not looking in the code. I could not build my skill set to be good enough for me to have a desire to last longer and stay interested in things. Fortunately, Rails turned out a completely different piece of cake.
After a few fixed red 500 screens and fighting with database setup my initial blog was finally set up. I was amused by how smooth it went. Firing up the first application was nothing like Spring or even Django. It worked right out of the box. And it was beautiful. At first, I was really hooked up on the idea of convention over configuration. The whole smart setup already is done for me by the framework. I had model, controller, and views and that was all I needed to make my application do the job. Do you have a problem not solved by the framework? Look up the docs, most likely you just don’t know the in-box solution yet. Sometimes I even guessed up the names of the methods I needed. Pure magic! If you have a problem that does not fit into the framework limits like authentication, admin panel, currency handling, integration with Google Maps or Stripe - just Google a
gem for it. Most likely you will find the one to suit your needs. The package manager was advanced and had a nice interface, scaffolding was bliss after all the boilerplate I had to deal with using Java Server Faces.
The community seemed to be fancy and I’ve got answers to my questions on StackOverflow and forums, most of them were asked before me. Nice people were doing nice things and I felt warm and welcome amongst them. Also, there were personalities. DHH, the creator of the framework, active on Twitter and his blog, always have an advice for you and steering the ship of Rails in the right direction, Yehuda Katz, co-creator of Ember.js and writer of numerous books about Rails and their surroundings, Avdi Grimm and Gary Bernhardt, whose screencasts I highly appreciated.
Appointment with disappointment
After a while, the first impression started to fade away. About six months in, I understood that I didn’t know Ruby well enough(I had no problems with Rails themselves, but the feeling that I could do more started to kick in). I learned more about Ruby and general OOP and started to realize some strange things. First of all, it turned out that a lot of things I used in Rails like
delegate were not a part of the Ruby core library. They were a part of ActiveSupport. They weren’t wholesome either, turning out to be a bunch of hacky monkey-patches that sometimes were in conflict with some of the gems I tried to use.
Secondly, Ruby turned out to have a
require method and everything did not really need to hang around in the global namespace as it was(and is) in Rails. I understood that it was purposefully made to serve as a convenience, but a bad taste of a big memory footprint and loading issues was here in my mouth. After that, my controllers got bloated with business logic. I googled the problem and found motto
thin controllers - fat models, so I followed it. But then models also started to bloat. I started to use concerns but they were not helping much either, putting out the logic that should have been in the class itself in the separate file, not really solving the problem correctly from the OOP perspective. Rails did not have any abstraction of their own, so I started to make them myself with POROs and patterns from the books I’ve read. Rails were hiding a lot of complexities you might have needed to comprehend and change deep down underneath the user level of abstraction, making developers employ hacky and wrong solutions to get the work done when it was not in line with the easy vision it had on how those features should have been done by convention. It seemed like configuration was not there when you were out of the conventional path. Gems also cluttered global namespace as ActiveSupport did, so sometimes they accidentally broke trying to redefine the same method. It was not looking like a strive for cleanness, rather a strive to get the work done no matter dirty or not. The standard way of handling actions on update/create - callbacks, also turned into a complete mess when the app got more full-fledged and filled with business logic.
Frustration started to raise and my feeling was like I was doing something that was not intended to be done with that framework at all. On the other hand, problems with ORM kicked in, every query harder than a trivial join with counting and some conditions in where was out of reach for the standard means of ActiveRecord, so I had to write SQL by hand or stick to Arel with quite a weird syntax. Rails also did not(and do not yet) support any means of view abstractions. Global helpers, erb, and partials - this is everything you have to deal with out of the box. No wonder I’ve started looking for better ways of handling the problems of rising complexity I had. When I got on the Internet, I’ve seen Sinatra, Hanami, ROM-rb, Roda and some other good libraries, but they were not that popular. There were voices of dissent, Elixir with Phoenix, Clojure, and Crystal, but they were trying to get Ruby attitude and culture out of Ruby ecosystem, while the original ecosystem was vastly occupied by Rails. Most Ruby developers were Rails developers and did not seem to have any problem with the framework being essentially the body of work and economic existence of the language. They liked what DHH said and followed the practices even though it hurt them sometimes. ‘Convention over configuration, TDD is dead, Rails is your application, you’re using Rails wrong if you have troubles with it, just use another gem’ they said. Then I realized that I’ve engaged in a cult.
Cult of easy
Let’s get down to the basics. What defines a cult? As Robert Jay Lifton says there are three main characteristics of a cult.
- a charismatic leader who increasingly becomes an object of worship as the general principles that may have originally sustained the group lose their power;
- a process of coercive persuasion or thought reform;
- economic, sexual, and other exploitation of group members by the leader and the ruling coterie.
Of course, DHH is a leader. He is a great entrepreneur and evangelist. I like the way he writes and the way he acts. He created Rails(not singlehandedly, but still). But what is the body of his words? What does he impose on us? Here are a few tweets of his for you to get the hang of it.
@paulca Fuck. That. Shit. Same complete wank. “Rails is not your application”. If you’re building a web app, of course, it is. — DHH (@dhh) June 29, 2012
Hello, my name is David. I would fail to write bubble sort on a whiteboard. I look code up on the internet all the time. I don’t do riddles. - DHH(@dhh) January 21, 2017
Those speak for themselves, so let’s move on to the culture Rails and DHH create in the Ruby community. He values easy solutions over simple ones. Why should you decompose your application when you can put the whole domain logic in the model and call it a day? Why use SOLID and GRASP when you can do thins more easily than before, no matter what cost it will have in the future. It is better to have everything at the reach of hand in the complete mess than sorted out with a few more hops to get to the functionality. Those solutions work in the short-term, but in longer scope, you end up with an entangled mess in deep need of a complete rewrite. With such an approach, that is dictated by a leader, Rails scale well neither cognitively, nor resource-wise. But the lord is still praised and his Rails vision pollutes not only Rails but also Ruby ecosystem.
This leads us to the next point. Process of coercive persuasion. Rails are not only bloating themselves and the minds of developers who work with them. They are contagious to the ecosystem. Active Support features slowly get merged into Ruby core and most of the gems need to be compatible with Rails in order to gain any popularity. A long time ago Rails killed off Merb. Now Rails are practically a monopolist in the Ruby field, so it is quite hard for new frameworks to get popular when libraries are polluted with Rails specifics, a huge chunk of rubyists are practically railsists and Rails were a thing for more than 10 years keeping in mind that business likes established and time-proven solutions. Rails are a cage and this cage transforms the mind of a developer to either give up and embrace sloppiness or get out either to a safe place like Trailblazer or out of the Ruby community to those prominent rubyists that created Elixir and Clojure.
Exploitation. Rails drain brains from the community like a vacuum cleaner. Why do something else when you’ve got the most popular solution on your fingertips? Why create general solutions when 90% of your gems’ users will be on Rails? Why bother if Rails are a default choice? Some people go against the current, but most of them don’t. So Rails popularity works like a snowball. The popular framework gets more popular because people choose it because of its ecosystem and support(Stackoverflow, Github issues, etc.) and then contribute to the ecosystem making it even more of a desirable choice. Many other visions, other libraries would have been created and existing libraries would be created differently if not for the hurtful impact and easy practices imposed by the monopolist. People either play by the rules or leave. Only a few stay to dissent. Here is a nice explanation of how it works.
Rails are a cult even though they do not employ sleep deprivation and do not claim soon apocalypse. Rails embrace and worship hurtful practices that do not work properly in the current world. Rails are easy to start with but following its best practices word by word is a good road to callback hell and complexity bursting out of control. Rails make developers worse by normalizing monkey-patching, denial of SOLID, GRASP, LoD and other good OOP practices for the mere immediate convenience. Rails kickstarted initial Ruby popularity, but they do a bad job of being a good citizen in Ruby country now.
Ruby without Rails?
I would like to have a solution in this section, but I don’t. Ruby popularity seems to be stagnating for the last few years and Rails move in the same old way only adopting the inevitable needed features or the ones that Rails Core Team and Basecamp need. There are voices of dissent and new frameworks but they do not skyrocket in popularity, leaving Rails a monopolist almost like it was in 2010. Some rubyists leave, some stay and face the problems that cannot be fixed with existing attitude, churn and framework structure. Will there be a solution? Will we get a better ecosystem and more choice? Will the cultists break their chains? I hope so. But only the future will tell.