Hacker News new | ask | show | jobs
by Tainnor 1869 days ago
> Is it imperfect and are there trade-offs involved? Of course, but there are with anything.

No disagreement here. But the argument was made that Rails "scales pretty well" and I believe this is wrong — and I don't even mean in terms of performance (that probably too), but also in terms of architectural complexity. All these problems are solvable of course, but Rails makes it IMHO harder than some other technologies.

1 comments

I haven't significantly worked with Rails since 2015, so I'm not up to speed with the current state of things, but in general I found that architecturally Rails can scale mostly okay, although it can be a bit tricky if you're not very familiar with the Rails internals, but it's not overly complex either in my experience. I was never a Rails super-expert either, and I managed to bolt on plenty of stuff for customers' specific needs, and the results worked fairly well and weren't too overly complex.

I don't doubt there are certain roadblocks though, and that some things fairly "simple" could be very hard and complex in Rails. I just never encountered them.

I've certainly seen a lot more overly complex crappy bespoke solutions when Rails + a few modifications would have been much better. This is like the old Greenspun's tenth rule: "any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp." – there are a lot of "ad hoc, informally-specified, bug-ridden, slow implementations of half of Ruby on Rails" out there.

Right now I mostly write web stuff with Go, which is the exact opposite of Ruby/Rails in almost every way. In spite of being so different, I'm fairly comfterable with both approaches, and I'm not entirely sure what I prefer yet (even though I've been doing this in Go for 6 years now); I certainly spent a lot more time on basic stuff that Rails just provides.

Rails is ultimately just a collection of libraries + some glue code, tooling etc., so you can, of course, build a well-architected Rails app with some discipline.

What I'm criticising is that a lot of the official guides (and/or DHH himself) often lead to problems down the road. For example, it is encouraged to do things through model callbacks. Except, once you have your send_email logic in a after_create callback and you figure out that you actually need to create users in different contexts too - e.g. in bulk updates if you need to import some data, where you don't want to always send an email - it will be painful to rewrite your code since you have no abstraction where that code should reside. Even DHH recognised this problem, when he pushed through ActiveRecord::Base.suppress [1] which was consided problematic by most everyone else (including the Rails core team). A better architecture would have a "service" or "concern" layer that would handle such things, but "the Rails way" doesn't advocate for anything outside of models, views and controllers. Though, to be fair, many real-world codebases do include such a service layer - but it's done differently everywhere.

There is also no abstraction for request validations. You're supposed to do all your validations in the model layer. But what if you have multiple requests mapping to the same model layer? Maybe the validations you want to run if an admin user updates a table are very distinct from the validations that should be run for a regular user. Again, while you can use ActiveModel objects for that, Rails doesn't particularly encourage this design and you can end up with a lot of coupling between your persistence layer and something which is essentially part of the business layer, and that can be hard to unentangle later.

Another famous problem IMHO is (by default) every single test loading the whole Rails context. This makes fast unit tests basically impossible and therefore TDD painful (which, IMHO, is particularly bad in a dynamically and heavily monkeypatched language - if you don't have static guarantees, you at least want to be able to test your changes quickly).

All of these are things that in other ecosystems - for example Spring - are handled much better. Now, I have criticisms about Spring too (slow boot times, excessive use of reflection, Hibernate is a mess, etc.) but at least it gives you some good tools to cleanly separate different layers of your application. For example, validation is generally done at DTO level, long before any of your data ever hits the database.

[1] https://medium.com/spritle-software/rails-5-activerecord-sup...

Yeah, I agree the MVC model in Rails is too simplistic. I never liked how everything is stuffed in models; back in Rails 3 (or 2?) it was even worse. I actually wrote a library to solve part of this, which inserted a "form" layer between the controllers and models. It worked quite well.[1]

Actually, Ruby on Rails in general is often "Rails + these 20 gems that everyone uses". I remember someone likening getting started with practical real-world Rails development as starting in Game of Thrones in the middle of season 5, which sounds about right to me.

[1]: https://github.com/bluerail/form_this