[HN Gopher] The Magic of Rails: exploring the principles and tec...
___________________________________________________________________
The Magic of Rails: exploring the principles and techniques behind
the framework
Author : ksec
Score : 77 points
Date : 2023-04-29 15:41 UTC (7 hours ago)
(HTM) web link (speakerdeck.com)
(TXT) w3m dump (speakerdeck.com)
| dlisboa wrote:
| I've been a Rails dev for many, many years, so I'm not shitting
| on it. My one concern with Rails is human scaling, not so much
| "web scaling".
|
| A lot of big companies use Rails and are successful at a large
| human scale. But one thing that is often not talked about is that
| they have the financial resources to hire the very best
| programmers in the world, and often they hire the very people who
| build the framework (e.g. Shopify, GitHub I think had a few
| members go through it, etc).
|
| This is critical when the biggest questions with Rails is: how to
| achieve clean code, modularity and separation of concerns; how to
| achieve high throughput.
|
| It doesn't surprise me that Basecamp says they never have issues
| with a huge monolith in Rails: they invented the framework and
| know their way around it. It doesn't surprise me that Shopify
| doesn't have issues with scalability: they have Rails core team
| members and Ruby engineers dedicated to creating an entire new
| Ruby VM.
|
| If the problems with Rails are solved by "throw the best people
| in the world at it" then it's a self-limited proposition. I have
| worked on countless Rails apps over the years, not one would pass
| the "this is just great code" test. They were not built by
| incompetent programmers. It's just that the "Rails way" needs a
| very heavy guiding hand behind it. In the real world that is
| often easy to lose: senior team members leave, you don't have
| time to rewrite parts of the code, you may not even have the
| expertise in-house to improve the codebase significantly. Bigger
| companies don't usually have these problems.
|
| And if you look at big Open Source Rails projects (Discourse,
| Spree, Gitlab), you'll often see the same patterns: 1000+ line
| models, non-standard Rails-way ideas like services and operators,
| hundreds of files all in the same place without any clear
| modularity... and these are not bad programmers at all. Maybe
| Rails at human scale is just hard, or maybe there's something
| about the framework that leads to this.
| [deleted]
| ulizzle wrote:
| The problems with Rails are the same as with Ruby as it was with
| Smalltalk: just too easy to make a mess (the nature of dynamic
| languages), and its community suffers from a nasty case of
| groupthink.
|
| Notice the cliche "Rails is so much more than a framework."
|
| The same magic that makes one so productive at the beginning
| (start-up stage) is what comes back to bite you in the ass when
| the project grows into an actual product; unless you are careful
| and willing to trade off speed-to-market, which isn't what you
| want to do with a startup.
|
| Catch-22 because the app has gone off the rails by the time you
| are successful, and everyone says: "Oh, you shouldn't have done
| that."
| lawn wrote:
| Incidentally I feel Rust is the reverse Ruby: more work
| (sometimes much more work) up front, but the big payoff comes
| in the long run.
| ulizzle wrote:
| Many typed languages are like that, but the big difference is
| that they admit the trade-off. In Ruby on Rails, dissent is a
| big taboo, so they blame the problems on the devs (the
| unwashed nameless masses) rather than tackle the problem
| itself.
|
| That's why you have all these different tools and concepts;
| since they try to sandpaper over all the magical complexity
| by adding more complexity, it becomes a no-true Scotsman
| trivia game.
|
| What trips me up tbh is how tech history repeats itself
| almost verbatim. The Smalltalk story is very similar but with
| a different cast.
| haolez wrote:
| Saying that dynamic languages are prone to make a mess is a
| kind of groupthink in itself.
| the_gastropod wrote:
| Frankly, I think the bigger cliche is: "sure, it's easy to get
| started, but Rails doesn't scale!"
|
| Rails apps are way over represented among large web-based
| businesses. Shopify, GitHub, Gusto, Airbnb, etc. There are
| countless examples of Rails scaling beyond what anyone could
| reasonably expect their web app to need.
| bdcravens wrote:
| This list cements the idea that without massive budgets Rails
| becomes a challenge once you reach a certain point. The
| argument against Rails isn't that it can't scale, but that
| doing so requires a certain level of complexity that is
| untenable for certain sizes and types of teams.
|
| Shopify has built massive tooling
| (https://shopify.engineering/shopify-made-patterns-in-our-
| rai...). Github was stuck on an old version of Rails for
| years due to the amount of customization they had done. (It
| was actually a big deal when they finally were able to run on
| the latest version: https://github.blog/2018-09-28-upgrading-
| github-from-rails-3...)
| karmakaze wrote:
| I've worked with Rails at two companies: 500px and Shopify.
| The former was what I take to be typical use of gems and
| monkeypatching magic. I didn't like it, though I ended up
| doing myself to get other issues under control. (And luckily
| much new development were as separate services in Go.)
|
| The Ruby/Rails at Shopify is much more sane (by my
| definition) looking much more like regular API made using a
| statically typed language (lots of Sorbet type info). There
| is of course dynamic magic, but tends to be limited rather
| than preferred, and where feasible static Sorbet type info is
| generated to match what the magic produces so users of magic
| can operate as if it was just a static typed library with a
| bit of DSL. There's enough in-house specifics that I wouldn't
| even call it Ruby on Rails, but rather Shopify Ruby/Rails and
| it's constantly evolving. There can be 3 ways of doing
| something: the old way (being phased out), the current way,
| and perhaps a new one being tested out in some part of the
| codebase.
| ulizzle wrote:
| Those companies are a product of the last wave, when Rails
| was very popular in tech, especially amongst San Francisco
| circles. There are also a lot of examples of that size that
| left Rails or never jumped on that trend. This is also an
| argument from survivor bias. You have to count the failures
| too, which we don't have numbers for.
|
| It's not that it can't scale; it's just that it's too easy to
| make a mess in the way, which would prevent you from doing
| so.
|
| So what ends up happening is that you pay for mistakes or
| someone else's, but at the end of the day, you are still on
| your own.
| ecshafer wrote:
| Could you share some examples of this?
|
| I am a bit over >1 year with Rails and I don't see this to be
| the case. There is some "group think" perhaps, but every
| ecosystem has that (Whats the "pythonic" way or Java way to
| write x). I work at Shopify which uses Ruby and Rails
| extensively, and I don't think things have "gone off the
| rails". We use other technologies where appropriate, but for
| the core business logic cases, Rails is fantastic.
| ulizzle wrote:
| You have to measure by time-to-market / team size. How much
| it costs to maintain the system, how long it takes to ship
| features, fix bugs, reach milestones, etc; which is something
| you can't say publicly, and even if the company did, it would
| be heavily doctored to make a good impression on
| stakeholders.
|
| That's why I think the argument is a weak appeal to
| authority. Throw enough money at a problem, and you can scale
| anything involving computers. Notice how expensive is Heroku.
|
| But you can't add more team members to a project and expect
| things to go faster, which is where the real problem with
| Rails lies.
| bdcravens wrote:
| The sheer amount of tooling that Shopify has built to
| overcome this is a good example.
|
| https://shopify.engineering/shopify-made-patterns-in-our-
| rai...
|
| "Going off the rails" isn't an indication that Rails is bad,
| as much as a claim that it can't fit the needs of a company
| with either splitting to other technologies ("We use other
| technologies where appropriate") or painting outside of the
| Rails lines.
| ecshafer wrote:
| Any company at scale develops these other solutions to help
| scale. A company using Java and Spring does the same or C++
| or whatever. Shopify seems to be unique at the largest (I
| think) Ruby/Rails shop, so they are leading the way
| developing a lot of these tools. I don't think that its
| significantly different than Google making Guava, Map
| Reduce, etc.
| tenderlove wrote:
| I hope that you'll watch the recording of the talk when it's
| released. The context of the "cliche" is with regard to the
| community, the framework, and why Eileen continues to remain on
| the core team. It's nothing to do with the design or
| functionality of the framework itself. :)
| nathants wrote:
| it's like the t-shirt from happy gilmore: guns don't kill people,
| i kill people.
|
| for whatever reasons, rails became easy to discover and use.
|
| that so many ended up committing git based crimes with it is not
| rails fault.
|
| personally i blame education and media. we can do better.
| joshmn wrote:
| I have been working with Rails for the last forever. I love Ruby,
| and I love Rails. Part of the reason why I love Rails so much is
| in slide 9: "Rails is designed to have agnostic interfaces."
|
| One of the reasons why I hate Rails is the steep learning curve.
| It's really easy to get something out the door with Rails.
| Whether or not it's maintainable long-term is what's up for
| debate. There are often 10 ways to get the same result: 1-5 are
| really bad, 6 and 7 are acceptable, 8 is good, 9 is great, 10 is
| perfect. Not everything has to be 10, or even 9, or even 8; the
| fewer 1-5s you have the better.
|
| The official "Getting Started" guides don't help this at all.
| Granted, they are indeed marketed correctly: they are for getting
| started. But it lends to this idea that that all Rails
| applications have to look that way -- the "getting started" way.
|
| Many of my applications (and many of the shops I'm brought in to
| "better") end up shipping with more than what comes out of the
| box. This might sound normal to folk on HN -- engineers are
| supposed to engineer things, after all -- but it's lost on many
| teams and orgs. ("Many teams and orgs" are largely teams and orgs
| we have never heard about, and there are plenty of them.)
|
| Taking a peak at my usual interface stack includes commands,
| components, decorators, forms, inputs, queries, presenters,
| serializers, and services. This is in addition to the default
| controllers, helpers, mailers, models, views.
|
| My ultimate takeaway from seeing over a two dozen "this Rails app
| is painful to use" situations in the last two years is that the
| developers hadn't extended past the original patterns that were
| given to them when they originally spun up the app. This largely
| results in losing a lot of the Rails magic because developers are
| (unintentionally wrongfully) forced to do things that goes
| against Rails' expectations.
|
| There are other things besides shipping better abstractions too,
| obviously. The one that stands out the most is controllers doing
| too much and becoming God controllers; developers get lazy (or
| just aren't aware) and simply define routes that are RESTful in
| the router, but aren't in the actual controller definition. This
| makes for a tangled mess.
|
| There's a way to make Rails as much of a joy to use as it is when
| you first hit `rails new` -- it just takes some experience and
| diligence. That can be said for every framework. But what can't
| be said for every other framework is that Rails makes it way too
| easy to write really bad Ruby code that, ultimately, gets you the
| "right" result. Avoiding those is the hard part.
|
| (I'm currently looking for work in case anyone wants to talk)
| ysavir wrote:
| > Taking a peak at my usual interface stack includes commands,
| components, decorators, forms, inputs, queries, presenters,
| serializers, and services. This is in addition to the default
| controllers, helpers, mailers, models, views.
|
| Would love to hear a short bit on what each of these does in
| your Rails codebases! I'm familiar with decorators, queries,
| presenters, serializers, services, but commands, components,
| forms, and inputs are new to me. Would be great to see what I'm
| missing out on.
| joshmn wrote:
| Sure, here's a brief tour:
|
| Commands -- I usually will ship with Rectify
| https://github.com/andypike/rectify. It's a great layer for
| my controller to handle request contexts. You might think
| this is a glorified service object but I'm not a fan of
| service objects unless they do just one thing (and are
| allowed to loudly fail).
|
| Components -- https://viewcomponent.org/ I'm not incredibly
| sold on them but they do clean things up.
|
| Forms -- Rectify has this shipped but it uses Virtus which is
| quite old and hasn't been touched in many years. Shipping my
| own similar is usually something like https://gist.github.com
| /joshmn/39eb6f302650e09743387710591ab.... Not all of my form
| attributes will map directly to a model, but I want my form
| helpers to actually help me so I need some sort of object
| that _can_.
|
| Inputs -- I'll extend SimpleForm inputs (something I can't
| live without) to DRY up my forms.
|
| All together, this is typically something like this (the form
| and command pattern, at least): https://gist.github.com/joshm
| n/65cfbccc6c64abe6d463ba9708b00... (not tested)
|
| There's usually also an `admin` directory since I also
| usually ship with ActiveAdmin or Trestle. I've fallen in love
| with the latter after making it behave more like ActiveAdmin.
| When I need to drop out of its usual constructs I'll just
| write a custom controller, but for the majority of
| administrative stuff I can get 95% of the way there with the
| DSL of either/or, freeing up time for domain-specific problem
| solving.
| pyridines wrote:
| Are there any resources you recommend for people trying to
| learn this style of Rails development?
| joshmn wrote:
| I do have a book coming out called Caboose on the Loose
| (https://leanpub.com/cabooseontheloose) that goes over how I
| build applications. It'll be for monies, but I plan on
| uploading it to torrent and piracy sites; included is a page
| that reads I'm cool if you pirate it. Happy to send an early
| draft; email is in profile.
|
| Some nuggets here:
| https://news.ycombinator.com/item?id=35755423
|
| A lot of it has been trying and failing -- a lot of times,
| across a lot of different applications. Many of which have
| been my own, but as of the last few years there have been
| other people's applications too.
|
| The first thing I look for when I go into someone else's
| Rails app is to grep through `routes.rb` and look for every
| route drawn that's not `resource` or `resources`. This has
| proven to be a good indicator of the amount of smells I'll
| encounter in the application. You can draw every route with
| `resources` or `resource` and get clean controllers, which
| leads me to my next point:
|
| Your controllers are the most important part of your
| application. It's the first and last thing your user touches.
| Getting them right is the most difficult part of architecting
| any application. "Fat models skinny controllers" does a
| disservice to models, though, because they shouldn't be fat,
| (insert transition)...
|
| Models should represent your database and nothing more.
|
| I could go on and on, and am happy to, but I'll quickly be
| writing a mini-book here and detract from Eileen's great talk
| at Railsconf. :)
| nasmorn wrote:
| Are you a freelancer coming in to help less experienced rails
| teams solve their maintainability issues? How do you mostly
| find work? This is probably the work I am most qualified to do
| as I also work with Rails since 2005. I am a bit worried to be
| tied so strongly to the stack in my offering but in reality
| that is what I mostly do.
| joshmn wrote:
| For the last few years I've been mostly W2. One of my selling
| points during the interview is that I've solved
| maintainability problems as team lead/in an architect
| position. When I have contracted, though, it's usually just
| word of mouth from people I've worked with before who
| remember me helping solve their maintainability problems.
| rtheunissen wrote:
| Replace Rails with Laravel and you get the same problem: the
| recommended patterns make it easy to get started but eventually
| work against you when things start getting big and busy.
| gv83 wrote:
| replace rails and laravel with django and...these frameworks
| are great, but require great discipline and the ability to
| factor systems correctly!
|
| but TBH, discipline + correct factoring is kinda the baseline
| to produce decent systems.
|
| It's still leagues better with django/rails than with
| "microframeworks" which are basically a giant spool of rope
| for anything more than a handful of endpoints
| 1123581321 wrote:
| I've seen developers, even experienced ones, struggle to grok a
| Rails app when it's been extended like that. Once they're up to
| speed they appreciate the decisions and contribute to further
| development. They're just not used to seeing that, as you
| describe. Have you found ways to make the extended engineering
| of Rails easier to understand for those used to limiting
| themselves to the out-of-box conventions?
| joshmn wrote:
| > Have you found ways to make the extended engineering of
| Rails easier to understand for those used to limiting
| themselves to the out-of-box conventions?
|
| Rails comes with a lot of the patterns I implement out of the
| box. Forms are just ActiveModel objects. Services are just
| POROs, as are queries. A decorator pattern can be done in 25
| lines of code (https://gist.github.com/joshmn/87f14dc7d6b45a7
| 2bd4e3f4fb8d82... Commands are a bit more difficult but
| anything that can respond to context with flow control
| handling is easy to grep.
|
| There's a fine line between implementing patterns and
| implementing patterns that behave as Rails expects them to.
| Thankfully, as mentioned in Eileen's talk, Rails makes it
| really easy to do this. While the underlying logic may not be
| documented on the Rails Getting Started guides, peaking under
| the hood isn't as intimidating as one would think.
| eximius wrote:
| Like any good magic trick, it's an illusion. While you're looking
| over here, I've secretly built an unmaintainable monolith!
|
| Tada!
| nasmorn wrote:
| As if micro services are inherently maintainable. Those are
| really orthogonal categories
| ecshafer wrote:
| Most "microservice" implementations I have seen are just
| monoliths spread out over many computers. I think breaking
| services up has a place, but I also think its vastly overdone
| and the hits to developer productivity, logging ability, are
| real.
| jeremymcanally wrote:
| Sounds like you need to hire better magicians. :)
| rtheunissen wrote:
| A framework is no good if it requires that the engineers
| working with it are excellent in order to not create a mess.
| A great framework or language _should_ empower participants
| with average ability and experience to produce good results.
| joshmn wrote:
| I think the problem is a little more subtle.
|
| With Rails, you can call `relation.map(&:id)` and
| `relation.pluck(:id)` and get the same thing -- an array of
| `id`. But using map is 50x slower because it loads the
| entire model into memory (ActiveModel is very expensive)
| before enumerating; pluck fires a query and hits the result
| set from ActiveRecord -- very inexpensive!
|
| Average ability participants then fall for this foot gun
| (and others like it) and end up designing things poorly.
| One overlook quickly turns into accelerant at scale. This
| isn't unique to Rails, but Ruby -- the delight that it is
| -- makes it almost too trivial to do.
|
| I've seen this happen at Rails shops many of us have an
| account on, where I wouldn't consider the people I worked
| with average ability participants either.
| gls2ro wrote:
| I dont understand how come a framework will help you
| avoid that.
|
| You can do a similar performance issue with anything:
| here is a raw example: give to anyone a non-ORM framework
| and the chances of someone hitting multiple times the DB
| to query the same records increases with team size and
| app scope. I am not sure there is a framework that can
| protect your colleagues from doing select * and then
| count the in memory objects instead of doing a count on
| DB.
| Sivart13 wrote:
| But if you're going to render those `relation` records in
| a paginated list anyway, pulling them into memory is
| superior so you don't hit another DB round trip delay.
|
| Which is to say, there's a lot of ways to do things, and
| trade offs between the different ways, but isn't that the
| case with any library or framework?
| joshmn wrote:
| > But if you're going to render
|
| Sure - if - that's fine and optimal! In larger apps,
| where there's more complexity, there are so many paths
| that aren't that trivial and that's where the trouble
| begins.
| dasil003 wrote:
| What's an example of a framework that meets this bar? In my
| experience, the messiness is generally a function of scope,
| team size and technical ability. Some languages /
| frameworks give you better or worse tools for managing that
| scalability, but context matters (right tool for the job)
| and none can guarantee a good result if the team is weak.
| What really matters is the technical leadership, who must
| have both the experience, and sufficient influence, to
| avoid going down a path of crippling technical debt that
| eventually strangles the system.
|
| As far as Rails goes, for all it's shortcomings, people
| forget what web development was like in 2003. The dominant
| paradigms were overwrought XML-powered J2EE with incredibly
| low power-to-weight ratio for web development, or
| unstructured PHP wild west stuff. These days every language
| has a framework that was heavily influenced (directly or
| indirectly) by Rails. Sure I wouldn't use Rails everywhere
| (1000+ engineer team: java, lots of concurrency:
| elixir/erlang, lower-level large systems: go/rust, etc),
| but it still has a great sweet spot from the prototype to
| moderate sized web app / API. Things that become weaknesses
| as you scale (eg. ActiveRecord pattern) are based on
| contextual tradeoffs that need to be made thoughtfully
| versus declaring them table stakes for all web frameworks.
___________________________________________________________________
(page generated 2023-04-29 23:02 UTC)