ActiveRecord considered harmful
It is practically impossible to teach OO design to students that have had a prior exposure to Rails: as potential programmers they are mentally mutilated beyond hope of regeneration.Edsger W. Dijkstra (paraphrased)
I love ActiveRecord. It was the first ORM Iâd ever interacted with. My first technical employer had commissioned a DBA, and so of course, we wrote all our own queries. Which was fine; I know my way around a JOIN or two. The problem came when it was time to make a new class; time to write âSELECT * FROM âtableNameâ WHERE âidâ=â%ââ⌠for each class. âJust copy one of the other small classes, hack out everything, and change the table names,â were my instructions. Fine. Whatever. But I knew there had to be a better wayâŚ
Along comes Rails. Holy crap, ActiveRecord is awesome! It writes the exact SQL I would have written myself! I donât need to do anything. This is the best thing since sliced bread. But years later, not everything is rainbows and sunshine. Iâve written a lot of crappy code, and most of it is due to following Rails âbest practices.â Which is totally fine! Rails is kinda getting old these days. Itâs no longer the new and shiny. But while Rails developers have gotten really good at busting out little CRUD apps, we havenât moved web application design forward in a really, really long time.
And thatâs what Rails did, really. That fifteen minute blog video was shocking. I know several people that threw away two or three week old projects and re-built their stuff in Rails within moments of watching it. And Rails has continued to lead the way in improving how we build rich applications on the web; the (not so but kinda whatever nobody but me cares) RESTful routing was great. The asset pipeline, though it has some bugs, has been great. The obsession with DRY has been great. The test obsession has been great. But Rails has also not been great in aiding us in writing maintainable software. Many of Railsâ design decisions make it difficult to write great software. It helps us write good software, but that isnât enough anymore.
The real problem is that to truly move forward, Rails will have to re-invent itself, and Iâm not sure that it can.
ActiveRecord is the problem
Iâm not going to talk about all of the problems Rails has today, but Iâd like to show you the biggest, most central one: ActiveRecord.
ActiveRecordâs greatest strength is also its problem: Tying class names to table names. This means that itâs impossible to de-couple your persistence mechanism from your domain logic. You can manage it through a combination of set_table_name
, making a bunch of Repository
classes, and careful coding⌠but then you might as well be using DataMapper. Except the Ruby library of the same name doesnât really implement the DataMapper pattern all that well either, having the same issue of tying it all together.
This has another interesting effect: it led directly to the âfat modelâ recommendation. While âget your stuff out of the controllerâ is correct, itâs lead Rails developers to build huge, monolithic models that are hard to test, and violate SRP. It took me two and a half years to realize that Ruby classes in the models folder donât have to inherit from ActiveRecord::Base
. That is a problem.
Weâve gotten into a situation with a local minimum: our quest for great software has lead us to DRY ourselves into a corner. Now we have code thatâs incredibly tightly coupled. Our âsingle responsibilityâ is âanything and everything that tangentially relates to a Post.â
ActionController is the problem
ActionController relies on instance variables to pass information from the controller to the view. Have you ever seen a 200 line long controller method? I have. Good luck teasing out which instance variables actually get set over the course of all those nested if
s.
The whole idea is kinda crazy: Yeah, it looks nice, but we literally just say âincrease the scope of variables to pass data around.â If I wrote a post saying âDonât pass arguments to methods, just promote your data to a globalâ Iâd be crucified. Yet we do the same thing (albeit on a smaller scale) every time we write a Rails application.
ActionView is the problem
The whole idea of logic in templates leads to all kinds of problems. Theyâre hard to test, theyâre hard to read, and itâs not just a slippery slope, but a steep one. Things go downhill rapidly.
What Iâd really like to see is Rails adopting a âViewModel + templatesâ system, with logic-less templates and presenter-esque models that represent the views. The differences between Djangoâs idea of âviewsâ and Railsâ idea of âviewsâ are interesting here.
MVC is the problem
If youâll notice, I basically have said that models are a problem. Controllers are a problem. Views are a problem. MVC has served the web well, even if it isnât the GUI style MVC that named the pattern. But I think weâre reaching its limits; the impedance mismatch between HTTP and MVC, for example, is pretty huge. There are other ways to build web applications; Iâm particularly excited about WebMachine. I donât have a constructive alternative to offer here, I just know thereâs a problem. Iâm still mulling this one over.
Itâs still good, even with problems
I love Rails. I build software with it daily. Even with its flaws, itâs been a massive success. But because I love Rails, I feel like I can give it straightforward criticism: itâs easier to trash something you love. The real issue is that changing these things would require some really serious changes. Itâd involve re-architecting large portions of things that people classically identify with Rails, and Iâm not sure that Rails wants to or can do that.
This post is light on examples. I want this to be the starting point of a discussion, not the end of it. Expect more, in detail, from me in the future. What do you think? Are these problems pain points for you? Are they worth fixing? Are they actually problems?