> if you open up any Rails application, it looks basically the same in structure whether it is the biggest Rails app there is or a new one.
I used to love this, untill I started to hate it. I am convinced this is a major contributor to why so many Rails apps turn into an unmaintainable mess over years.
Who measures onboarding in hours? It's fine if it takes a day or two to understand the domain. And the framework. And how they tie together.
Talking about the domain: Rails puts "the plumbing" up front. Its how it achieves this consistency. My app is never about "models" or "http" or "databases". My app is about medicine-journals. Or loan-request-management. Or CRM. Rails makes itself important, at the cost of my domain.
Rails' opinionatedness makes it so that this is hewn in stone. Its MVC is a given - and that's fine - major architectures should probably be dictated by the framework. But it's ORM - ActiveRecord also is a given. And that's not fine because AR (as an architecture and as how Rails implements it) is very unfit for a large category of applications. It's virtually impossible to swap AR out for anything else. Same with templates/views, JS, Caching, and many more: you can -in theory- replace them with a drop-in alternative. But you cannot -not even in theory- replace them with something that has an entirely different architecture or concept. This makes Rails not Omakase, but actually McDonalds: wherever in the world you come, you know exeactly what to expect, but it also makes boring and bland: no-one eats 7days/week McD.
This makes all Rails apps look alike. Despite the fact that not one of the apps that "we" are building is alike another. Domain. Team. Project Planning. Combine any of them and the projects demand different things, but with Rails you are out of luck. Regardless if you build the next fintech platform with a team of 120 senior devs over 6 years, or you hack your "marketplace for coffeelovers" over the weekends alone: you get The Rails Way. One of those might be a perfect fit. But it's impossible they all are. Each team gets the same "menu". And in many cases it simply won't fit.
You're building CRUD apps. The conventions work and are extensible for teams of 1, 10, 100 and 1000s. You are not special and neither is your product. Companies making millions or billions of dollars have used this framework successfully.
This level of bike-shedding is what makes conventions necessary especially when dealing with the typical hyper-pedantic software developer. Just the thought of having to debate where to put every file in a project or having to invent a new folder structure for every app we build fills me with a bizarre mixture of boredom and rage.
As with everything in life the people that whine about the medicine the most are the ones that make it necessary.
Your model of companies using Rails with 1000s of engineers is almost comically naive. Look at what Shopify and Github have to do to make Rails work for them. Also look at the non Ruby code engineers there are writing and ask yourself why they might be doing it. Rails is not a religion. It can be good at what it does without having to go on a crusade when people point out its substantial limitations.
Totally, Rails is a great tool. So
is my gunsmith hammer. I can like it for what it does without arguing it's the best thing in the world for cutting wood or joining two pieces of metal together.
you're seriously convinced they would have had no problems if they chose something else? every codebase that lasts that long and is used that much is going to face very hard challenges as it scales and meets new landmarks.
the maintainable codebase from day 1 to day 5000 is (mostly) a myth. yeah maybe some other stack could have faced different tradeoffs.
I'm also curious about YOUR choice of stack at this point.
I never said that some other stack wouldn't have problems. My point was that Rails is great at some problems and awful at others. No idea how this can be controversial at all. My impression seems to be that there is a group of fanboys that are not able to have any intelligent conversation on what their favorite tool is good for and what it's not good for.
In my day job I use mostly Rails. My team is starting to rewrite some of the services we own in Golang because Rails is no longer a good fit for the problems and scale we use it for. Rails was great to get started fast.
Nothing wrong with using a press instead of a hammer at some point, they are just tools.
The Rails app I scaled posted half a meg of JSON on every save-request every 10-15 seconds. In Rails, we parsed it, converted some parts into HTML nodes in Nokogiri, sanitized it, and saved it to both mysql and cassandra.
It wasn't a problem other than that a better initial design (nothing to do with rails) could have made passing all that data not needed, which was better for mobile. We had about 600,000 customers.
How many requests per second are you talking about roughly? One major problem we face is that downstream services also have performance problems and have multi second response times. While waiting for the response, a whole rails worker is sitting idle, taking up hundreds of megabytes of memory for seconds.
Is there any comparably complete framework that does not need any significant adjustments even when it's used by 1000s of developers building the same app?
Can confirm. Nothing worse than figuring out what sort of "magic" is affecting a route in a huge Rails app. Oh look, a before_filter in a super class 4 levels up that is defined in an include helper. But wait, why isn't it affecting all calls and only some? Ah there's another chain of filters that you only can know about if you are familiar with the older Rails version API.
Rails is the "goto:" label of web frameworks. It's unbelievable how much it encourages spaghetti code and misdirection directly via its conventions.
I don't think it's necessarily bike shedding, and actually a lot of the sentiments resonated with me. Rails is a tool that does a tool's job. It's nice to know a hammer does hammer things when you're expecting it. If you need a level, maybe use a different tool. I think the main issue is everyone expecting it to be "one-size fits all." It was never meant to be that, really
This is part of the problem with your claim - many of us are not building CRUD apps, we are building complex enterprise software and there are unique challenges to solve.
At the end of the day, all programming is CRUD at various levels of abstraction. You read some data, and then create/update/delete various forms of related data in various locations, like your DBMS or maybe a file or your GPU's VRAM
Rails provides a way to approach CRUD via MVC. Controllers are your API. Models are the connection to the Database. Views are what the controllers render.
If your app doesn't do these 3 things - API, Database, and representation of your API - you don't need rails (I bet you do those three things). Other than that, you're free to layer on whatever architecture via ruby that you want on top of these basic rails constructs. If you don't like it, again don't use rails. It's opinionated for a reason
Then I think the focus should be on the API. At enterprise level, the API becomes the language, and the frameworks (and even departments to an extent) become the functions/methods.
on the off chance someone doesn't understand the subtext here.
BaseCamp is DHH's company's product. DHH is the creator of Ruby on Rails. He literally create RoR to build BaseCamp, which is exactly the type of software the other poster is claiming is problematic for RoR.
DHH is on record as having said RoR was evolved organically from the early code of BaseCamp.
> which is exactly the type of software the other poster is claiming is problematic for RoR.
I wasn't. I specifically did not mention any concrete examples. I presume parent misread it as "for project management rails is unsuited" which, indeed it's not: specifically because PM is very much CRUD and has relatively little and/or relatively simple business logic (It's not for nothing that the hello-world of nearly all frameworks around CRUD are "TODO lists", the simplest form of PM).
What I tried to say, is that your domain, your team, your timing, your specific planning and your kind of project and any combination thereof has different needs. A setup, architecture, framework, fits one or a few of these perfect. But never all of the combinations of them. Nor over time (today you are a one-man-shop, tomorrow a team of 6. Today you build a full-stack web, tomorrow you need APIs for integration. Today you build a CRUD app for some medication journal, tomorrow it pivots into a complex tool for medical research.)
I don't know what exactly the complaint is here. You don't like that Rails has a common structure?
> It's virtually impossible to swap AR out for anything else.
I've used Mongo and a number of other ORM's, why can you not use other ORM's exactly?
This just sounds like you don't like frameworks and want to build things from the ground up, because most of the complaints you make are just not true. Maybe you are just inexperienced with Rails because you can swap out almost anything.
because behavior is an unspoken part of contracts.
I can't reasonably swap out an array with a linked list even if the official contracts are the same.
this is why things like DAL's are created, they give you an opportunity to deal with the differences in behavior.
The issue with frameworks like RoR that use AR throughout is that the queries are sprinkled throughout the codebase, giving no opportunity to fix such behavioral differences.
What happens is every ORM then attempts some sort of "query reuse" and they do so badly because it's not possible to do it well with the contracts they expose. It creates code where you can't ever reason about the query that's actually being generated.
What kinds of queries are sprinkled throughout that are not part of AR, or depend on AR?
Sure, if you are going to swap out AR for another ORM in the middle of an established project you are going to have a bad time, but if one is doing that I have larger questions.
I wasn't saying that we want to swap it out in the middle of an established project, but that it's impossible to do so in a greenfield project too.
there's MongoID and it's OK-ish, -a brilliant piece of work though!- but not particularly good inside Rails yet the best alternative example there is. Yet with this (naturally) many gems won't work either. Everything in the community simply presumes Rails' AR is always there. Because it practically always is.
ROM-rb, and Sequal all attempted to be "plugin replacements" but the author of the first rage-quitted at some point exacly because Rails (the dev team) refused some compromises or even abstractions that would allow swapping AR out for something that fits SomeProject better, at the start.
I must be misunderstanding the question because anything that queries in rails uses AR and that's often done in both lib code and controller code rather than behind a dedicated module boundary.
> because anything that queries in rails uses AR and that's often done in both lib code and controller code
How is that different from any other framework ever? You have to query the DB somewhere. Rails makes it incredibly easy to swap out databases. Much more so than any other platform I can think of.
Nothing is making you use AR at all. This is a non issue.
since "plumbing" is an essential part of *every* application, I'd rather not focus on it all the time.
I maintained both kinds of framework-heavy and "organic home grown just libraries" apps, and you know what? I totally prefer framework heavy stuff; at least it has battle tested facilities for everything, and I can expect consistency instead of fomo-driven/resume-driven development.
my last homegrown framework was a nasty 60k LoC api that did like 10 operations. total business logic was 3000 lines, including fn declarations and docs. just transaction scripts. the remaining 57k were a gargantuan amount of boilerplate that gave absolutely nothing to the project, and all in "typed python" which is like 0.9x java verbosity. a massive piece of shit.
Me neither. Which is why I want it tucked away and out of sight and out of thought.
My app is about Medicine, or Projects, or Coffee, or Orders. Not about Controllers, Models, HTTP and DatabaseLayers. Hence I don't want to work day in day out in this plumbing but rather in my domain¹.
Also, there's this false dichotomy, where "no framework === diy mess" That's nonsense. It's perfectly possible to create a well architectured, clean, maintainable and scalable system without the constraints of a framework. You don't need to write your own HTTP handling or database layers if you forego a frameworks: it's what libraries are for. Or microframeworks. Or both.
either you're very lucky or I've been very unlucky with our respective teams, as yes, it is perfectly possible to create a decent application without frameworks, but it's also incredibly unlikely, given that the average coder is incredibly mediocre at best and often does not even know basic engineering practices ~ i.e. see the success of function-signature-stealing-decorator-heavy web frameworks in py; that alone makes impossible to use constructor injection without "advanced" concepts like closures, but who cares, just instance from inside the controller and monkeypatch!!!1oneone
If the team is VERY skilled, VERY small and VERY able to keep the culture going forward indefinitely I'm all in for the homegrown framework; if not, I'd rather have a set of well done facilities that accrued many years of manhours i.e. cli commands out of the box, testing framework already well configured with decent standars like tx-wrapped tests, and so on, decent security, admin panels...
it's not a technical matter, it's a social matter. social matters are more important than technical ones.
Rails/DHH took already established design patterns and made strong opinions into a convention on the folder hierarchy of where you store your code. You can change that hierarchy, its not set in stone. It will require a lot of change. I've been on teams and it isn't just on-boarding time, its countless hours trying to find code written by someone no longer there that had their own layout of where files should go. Without conventions, people will run amok with a file structure. Multiply that by the number of developers on the team with attrition and different view points on organizing files and it can be a giant mess after a number of years. Its all a waste of time and has nothing to do with the quality of the code, what domain the application is in or anything really.
If you love Ruby there are other libraries out there like Sinatra [1] that don't have the conventions of Rails.
> so many Rails apps turn into an unmaintainable mess over years
Does this happen more often for Rails than for other frameworks?
There are many ways in which a Rails project can get derailed. But they seem not different from regular tech debt and I could imagine equivalent problems in other environments.
> AR (as an architecture and as how Rails implements it) is very unfit for a large category of applications
If you plan to build an application belonging to a category where AR is not a good fit, why use Rails?
I wouldn't claim that Rails is a good fit for all problems. Still, I'd say the structure and defaults of Rails are one of its strong benefits.
Or do you mean "application" as in "usage" - i.e. that over time you might notice a problem that's hard to solve with AR? Could you give an example? I'd guess you could use a different approach for a single task, or even move from Rails to a different tool if that becomes a big issue.
> Does this happen more often for Rails than for other frameworks?
Yes. But there are many frameworks where this is even worse. Rails, however, is highly opinioated, and does not allow you to pick and choose your parts (this is a design decision). That has lot's of benefits, but the major downside is that it will never fit perfectly (or as close as one may get). Most often an "off the rack suite" is fine, but we all know that a tailor-made suit is just that much better/prettier/comfortable/durable. Same here: Rails will probably fit your project OK, but that's not good enough for many projects.
AR is a another big contributor, as is the way Rails has its MVC set up. Tight coupling, no separation of concerns, etc. etc.
As you say:
> If you plan to build an application belonging to a category where AR is not a good fit, why use Rails?
Which is my entire point. Yet it happens. Far too often. (I'm a freelance consultant who deals with these failing Rails projects on a monthly base. And occasionally a very pretty one)
i’m preparing a talk for either railsconf or railsworld that puts this question/concern to the community. two times i have deviated from the standard apps/{models,controllers,views} layout and i have profited massively, especially in terms of conceptual integrity and abstraction. all my code lives in app/lib under domain-specific directories. this includes the models. the only part worth separating is the web router and controllers. i have achieved separation between my app and the web parts that aren’t offered by default by rails. i’m hoping to share my experience, for the community’s consideration.
I've had the pleasure to work on such kinds of Rails apps a few times. It was almost magical, compared to all the other common Rails apps with their ever accumulating fat models, complex controllers, untestable- coupled classes and so on.
One had this what you describe: everything in /lib, and the MVC merely delegating to that. MVC downgraded to what it should be: plumbing that binds together your domain stuff.
The other did something similar but had it in gems (bound as Railties/engines). IT was a bit more cumbersome, as one had to release a new gem before being able to integrate it in the rails app. It forced a very solid separation of concerns.
> compared to all the other common Rails apps with their ever accumulating fat models, complex controllers
i interpret fat model as: what can be move to the model, sits better in the model (directory). things that cannot be moved to the model: the request, the response, the session. not set in stone, but usually this works.
what i regret about older Rails code i wrote was the gluing of all biz logic to ActiveRecord ORM models (akin to, yuck, Hibernate entities), that also contain DOAs, form validation and all business logic. now i tend to split these out: form dtos that do validation, repos with queries, simple record classes, etc.
fat signals homogenous big thing, but is actually where most of the application lives. i coudl call it lib as well.
Except that Models are also Records. So by definition they don't separate concerns: for one the separation of concerns between "storing/retrieving stuff"
and "all the business logic stuff".
This lack or SoC, invites other tight coupling: For example, in Rails we commonly couple our models to our database design. You need a Medicine Adjustment? Better have a "medicine_adjustments" table, eventhough its more an Event than a record. Sure, you can pick and choose pieces of ActiveModel, and build models that aren't backed by database-tables, or by multiple tables. I do that all the time. But its far easier to just tightly model each Model around a Record/db-table. And because it's easier, its what most of us (especially juniors not bitten by it years later) will do: the easy way.
In the book "Growing Rails Applications"¹ has the -IMO- best practical patterns to solve this, but it goes right against the "you open a rails app and know what's happening": neat patterns, well manageable, and well documented, but very non-railsy.
i doubt. the further down the wedge drives the harder it gets to make the components communicate, and i think when communication gets hard we’ve probably gone too far. that’s not even taking into consideration the mechanisms of managing engines/gems.
>Domain. Team. Project Planning. Combine any of them and the projects demand different things, but with Rails you are out of luck.
I mean you could have at least picked some better example. Considering Rails was precisely extracted out from Basecamp which is "Domain. Team and Project Planning".
I am convinced this is a major contributor
to why so many Rails apps turn into an
unmaintainable mess over years.
I have two easy answers to why Rails apps turn into messes.
1. Any non-trivial app in any non-trivial language/framework usually becomes a mess eventually, given enough commits and developers
2. Rails (specifically, ActiveRecord) won't stop you from creating circular dependencies between models. This is easy to avoid, but it doesn't warn you about this or try to prevent it. So 99% of Rails apps have like, a User model that depends on (and is depended on by) most of the other models. This is far from a Rails- or ActiveRecord-specific issue though.
Who measures onboarding in hours?
You're right of course: that's a one-time cost. It's nice to optimize this but as you say, it's a one-time cost. Assuming a developer will spend multiple months or years working on the app, it would be better to optimize for the rest of that time.
However I think the standardization on MVC pays off here as well. For apps with multiple developer teams you may constantly be "onboarding" as you move between different areas of the app. And you can move forward with less bikeshedding.
And that's not fine because AR (as an architecture
and as how Rails implements it) is very unfit for a
large category of applications
I agree, although I also feel strongly that AR is very good at getting out of the way and letting you just use raw SQL when you want.
So IMO/IME it works well for scenarios where some of your data is AR/ORM friendly and some isn't.
Same with templates/views, JS, Caching, and many
more: you can -in theory- replace them with a
drop-in alternative
I can't agree. A lot of Rails projects use HAML instead of ERB and while I never set that up myself, I wasn't under the impression that it was a hassle.
Rails' caching backend has been seamless to swap between DB, Redis, in-process, and Memcached backends. As far as the caching "frontend", it's entirely optional, so I can't really imagine there is an obstacle to swapping it for something else? Like, you never have to use `Rails.cache`.
As for the JS side of things, I don't think I totally agree. There aren't drop-in alternatives, but you don't have to use Stimulus, and you can certainly use your own.
This makes all Rails apps look alike.
This is good in a lot of ways. Less bikeshedding more building. But, also... I have to admit. I am bored to tears with Rails. Happy to be working in another language/framework for the moment and possibly forever.
I disagree. This presumes that there's some initial "onboarding" process, and that once that's done you just now will know the structure of the app for all future, never spending more effort on it.
That's only true for trivial apps. What actually happens in bigger codebases is after you stop working in some section of the code for a few weeks, it falls back out of your head and you have to figure it out again. Additionally, without conventions other members of your team are constantly inventing new structures and connections between things.
So really this lack of consistent organization is a continuous drag, not a one time cost.
The key is to build a Ruby app and then provide HTTP access and persistence using Rails. You can find a lot of articles about this by searching for Rails and hexagonal architecture.
My biggest issue with trying to do this is ActiveRecord. I'd much prefer the repository pattern.
I couldn't agree more. There is also a technology aspect to it. Rails is objectively veeeeeery slow. Concurrency support is nonexistent. This is not a good
fit for all problems. It also to some degree prevents you from breaking out the parts that would benefit from a different language into their own services (Rails needs to call them, but it's really not good at IO).
Is there a comparable framework that does what Rails does but is somehow 10x faster? I wouldn't use Rails for everything but the fact that plenty of companies like Shopify are serving millions of requests per second with it shows that it's probably acceptably fast for mega scale apps.
Phoenix framework on elixir does come close to this. Designed by people with a background in ruby and rails, and has much of the same design philosophy.
That said, there are areas where Phoenix can't match rails, such as having access to a large developer community and a large existing base of libraries.
> I don't know how they measure it, but other measurements have shown different results
The big difference is the blog post you linked performs a very basic GET request to an endpoint. It mentions it doesn't hit the database or deal with caching. It's basically a non-realistic hello world that is good at isolating performance of a specific library but doesn't show how it fits into the grand scheme of things.
The other link performs multiple database queries as part of the request which goes back to the old saying that for a huge portion of web apps you're I/O bound (AKA waiting for something else such as the database).
Rails does everything. You can build a stateless API gateway with it. Is it great for that particular use case? No. Your question about frameworks with similar capabilities is pointless because my point was that there are use cases where the capabilities of Rails are not a good fit.
You said it's objectively very slow. My question is relevant because your point begs the question: Slow compared to what?
If you want to give an honest apples to apples comparison then, okay fine, what framework that does everything that rails does is considerably faster?
Is a Ferarri faster than a dump truck? Sure, but they have different uses. Try hauling gravel with a Ferrari. For the class that Rails is in, there isn't anything as feature compatible that is also an order of magnitude faster.
Ruby/Rails is not great for efficiently transforming megabyte sized blocks of JSON into differently structured megabyte sized blocks of JSON, just to give you one example. Golang/Rust/Java is better suited to that. Other use cases are for example any ML-Workloads where Python's ecosystem is much superior to Ruby's.
That being said, you missed my original point, which is that there are problems where you don't really want Rails implemented in a different language because Rails is not a good tool to solve that problem. Think hammer vs saw. You are asking for a different brand of hammer that can cut wood better. Wrong question.
Obviously not every took if right for every job. But your claims that Rails is slow because for what it does there are not many good replacements. Go is a language not a framework.
This reads like someone who doesn't understand how to use a tool so they think it is broken. I've worked on Rails apps that outperformed Spring/Java apps routinely and node apps routinely at very large scale. You're very rarely bottlenecked on CPU in a modern CRUD app, much more often, it is the database.
It sounds naive to call the framework that runs github, that almost everyone in the world pushes their code to "veeeeery slow" and I don't know what you mean by "bad at io" in any context where that is a problem for Rails.
But Ruby is one of the slowest languages around. And Rails adds a lot of runtime overhead to that. It really is very slow out of the box.
And that matters for virtually no-one¹, because almost no-one is running their rails app at that scale.
That something would outperform Spring is really due to technical choices, the stack, suboptimal use or libraries. Because Java is undeniably multitudes faster than Rails; in everything.
¹ This used to be my strongly held opinion. But I'm shifting around since we're in a the middle of an unprecedented energy/climate crisis and a slow rails app is gobbling up electricity much more than a highly tuned one. Or the same service rewritten in Go or Rust or Java will.
Stateless API gateway making HTTP calls to other services, which have response times in seconds for various reasons. Rails throughput ~20 requests per second. Golang rewrite throughput: 200k requests per second. Same hardware.
I helped write what might be a similar API gateway prototype in rails (made a DB query and decorated downstream requests with auth/role/etc headers). You might have threadpool/process/concurrency tuning to do. Even then, I don't think rails is a good solution for what is essentially an HTTP proxy, and I would've pushed for a different tool if time wasn't an issue. Rails was fast to build, I'll give it that. We ended up getting downstream service to $1M ARR so rails wins out against my "let me write it in XYZ language/framework" again somehow.
This is the point I wanted to make. Rails is great for some problems, not great at others. I can tell you for example that it's not great at transforming 2MB of JSON into a differently structured 2MB of JSON.
I used to love this, untill I started to hate it. I am convinced this is a major contributor to why so many Rails apps turn into an unmaintainable mess over years.
Who measures onboarding in hours? It's fine if it takes a day or two to understand the domain. And the framework. And how they tie together.
Talking about the domain: Rails puts "the plumbing" up front. Its how it achieves this consistency. My app is never about "models" or "http" or "databases". My app is about medicine-journals. Or loan-request-management. Or CRM. Rails makes itself important, at the cost of my domain.
Rails' opinionatedness makes it so that this is hewn in stone. Its MVC is a given - and that's fine - major architectures should probably be dictated by the framework. But it's ORM - ActiveRecord also is a given. And that's not fine because AR (as an architecture and as how Rails implements it) is very unfit for a large category of applications. It's virtually impossible to swap AR out for anything else. Same with templates/views, JS, Caching, and many more: you can -in theory- replace them with a drop-in alternative. But you cannot -not even in theory- replace them with something that has an entirely different architecture or concept. This makes Rails not Omakase, but actually McDonalds: wherever in the world you come, you know exeactly what to expect, but it also makes boring and bland: no-one eats 7days/week McD.
This makes all Rails apps look alike. Despite the fact that not one of the apps that "we" are building is alike another. Domain. Team. Project Planning. Combine any of them and the projects demand different things, but with Rails you are out of luck. Regardless if you build the next fintech platform with a team of 120 senior devs over 6 years, or you hack your "marketplace for coffeelovers" over the weekends alone: you get The Rails Way. One of those might be a perfect fit. But it's impossible they all are. Each team gets the same "menu". And in many cases it simply won't fit.