[HN Gopher] An Introduction to Metaprogramming in Ruby
       ___________________________________________________________________
        
       An Introduction to Metaprogramming in Ruby
        
       Author : unripe_syntax
       Score  : 69 points
       Date   : 2023-07-26 11:18 UTC (1 days ago)
        
 (HTM) web link (blog.appsignal.com)
 (TXT) w3m dump (blog.appsignal.com)
        
       | mvdtnz wrote:
       | The only guide to meta programming I give to developers at my
       | company is "don't use it, it will not pass code review".
        
         | iraliaf wrote:
         | why?
        
           | the_sleaze9 wrote:
           | It's a foot gun (incoming strong opinion)
           | 
           | The single most difficult thing in software development is
           | the fact that the system doesn't exist, it is defined by
           | mystical incantations, and we work on that invisible system
           | by changing the instructions to build it.
           | 
           | Anything that makes the understanding or "building" that
           | system mentally is no-go.
           | 
           | Flashback to one of my favorite debugging stories where an
           | entire java code-base was meta-programmed into existance at
           | runtime and would constantly throw errors to lines of files
           | that didn't exist.
        
       | actualwill wrote:
       | Ruby meta programming is awesomely powerful, but also one of the
       | main reasons I never want to work in another's Ruby codebase
       | again. There is always some developer who read some article like
       | this and invents their own DSL to solve a problem that didn't
       | need one. It's pure pain to debug it.
        
         | jweir wrote:
         | I love Ruby and we use Ruby and we do not allow meta-
         | programming. Too difficult to maintain.
         | 
         | Even `send` is frowned upon, but allowed under some
         | circumstances.
        
           | actualwill wrote:
           | If you have some group that all understands and checks each
           | other from the beginning, Ruby is probably great.
           | 
           | However it was every startups default choice for a while, and
           | those code bases get wrecked and have no oversight until way
           | later. A lot of bad ideas becomes foundational. This scenario
           | is far more common than good Ruby code bases. It's just
           | easier to rule out Ruby when looking for new jobs.
        
         | f6v wrote:
         | Classic: saving two lines of code, but completely breaking
         | maintainability.
        
           | tremon wrote:
           | Exhibit #1: rake's DSL syntax. It allows "neat" syntax
           | abominations like                 rule :name, [:param] =>
           | [:dep1, 'dep2'] do |t|
           | 
           | where every argument except the name can either be missing,
           | single (value) or multiple (array). Sure, it has the
           | "advantage" that it's syntactically valid Ruby code, but it
           | then requires some 70 lines of awful code to actually parse
           | that data into a usable construct: https://github.com/ruby/ra
           | ke/blob/7b50e9dc37abc57fd365c16cb1...
        
         | UncleOxidant wrote:
         | I feel the same. For my own projects where it's only me working
         | on the code it can be really nice, powerful and big
         | productivity boost. But if you start having multiple people on
         | the codebase it's not going to be fun to debug.
        
       | Alifatisk wrote:
       | I learned how fun metaprogramming is but also realized that it is
       | a double edged sword, so if I want the codebase to be
       | maintainable then I'd stay away from metaprogramming as much as
       | possible, it's a hell to debug, but also very powerful when you
       | want to construct your own DSL etc.
        
       | ye-olde-sysrq wrote:
       | Ruby is the only language where extensively deep magic feels okay
       | to me, for some reason.
       | 
       | I don't like it in python, I don't like it in Java.
       | 
       | But e.g. in Rails, sure I bump my head sometimes, but overall I
       | like how magical Rails feels because it lets me go so fast.
       | 
       | Maybe it's because Ruby alone is willing to sacrifice so much
       | speed (though not THAT much vs python tbh) and is willing to go
       | all-in on it, that they enable magic to be so deeply magical that
       | it can deliver adequate value to compensate for being more
       | inscrutable?
       | 
       | Whereas other languages' metaprogramming systems keep you a
       | little more leashed.
        
         | vlunkr wrote:
         | Makes sense. In some ways there's less magic to ruby, because
         | it's not using macros, templates, reflection, generics etc. In
         | other languages you're stepping out of "normal" code into
         | "special" code to make the magic work.
        
         | pseudocomposer wrote:
         | Rust's macro system is the first I've seen with the same
         | potential. But of course, an equal to Rails has yet to surface;
         | and even if one does, being a compiled language still
         | counteracts a lot of its ergonomics.
        
           | ramenbytes wrote:
           | Excuse me netizen, do you have a moment to talk about our
           | Lord and Savior, Lisp?
        
             | pseudocomposer wrote:
             | With Lisp, is it even metaprogramming? Or maybe everything
             | is metaprogramming...
        
         | interstice wrote:
         | I loved it.. until something broke and searching a method name
         | didn't work because it was using dynamic method names. A full
         | day of unpacking the Spree Commerce shipping system put me off
         | a bit.
        
           | RussianCow wrote:
           | I'm not super proficient with Ruby/Rails but we use it for
           | our backend at work, and this reflects a large portion of the
           | time I've spent using it. People who use Rails every day take
           | for granted just how much magic there is and how confusing it
           | can be for someone less experienced with it.
        
           | acchow wrote:
           | Ruby metaprogramming breaks `grep` and static analysis tools.
           | This is a no-go for any large project for me
        
           | ye-olde-sysrq wrote:
           | Yeah sure - it absolutely has drawbacks. I too have spent
           | time going "what the heck is this actually doing". But man
           | when you're not debugging one of those wonky things, Rails
           | just feels like programming with a rocket strapped to your
           | chair.
           | 
           | Is it the most maintainable code? No. Is it the easiest to
           | understand? It depends tbh. Rails provides so much out-of-
           | the-box stuff that lots of rails apps end up looking
           | sufficiently similar, especially if they're small-to-medium-
           | sized. But yes you can end up writing some dreadful spaghetti
           | without a bit of discipline, but imo that's true of python
           | and (node) js as well.
           | 
           | But damn is it SO fast to get up and going. And given
           | product-market fit is why most projects and products fail,
           | it's hard to argue against using Rails for me, since if I'm
           | even still here to complain about it later, that's already a
           | win.
        
             | Alifatisk wrote:
             | > Rails just feels like programming with a rocket strapped
             | to your chair.
             | 
             | I know this feeling!
        
           | rakoo wrote:
           | Same for me. I am now happily using Crystal as a ruby-with-a-
           | compiler and the joys of the beginning are coming back.
        
         | fishtoaster wrote:
         | Ruby's metaprogramming allows you to create _really_ nice,
         | ergonomic abstractions. I can write `has_one :posts` in a User
         | model class in Rails and a _ton_ of useful functionality pops
         | into existence.
         | 
         | On the other hand, that deep magic metaprogramming can be
         | _really_ hard to follow if you need to understand how it works.
         | Tracing back through (or even debugging) a metaprogramming-
         | heavy codebase is a nightmare.
         | 
         | I'd argue that deep magic metaprogramming is great for when you
         | have abstractions you almost never need to dig into. Rails is
         | great because it's relatively rare that I need to go spelunking
         | in the rails codebase itself (and thus understand the deep
         | magic). Instead, I can rely on a huge pile of documentation,
         | stack overflow answers, conference talks, etc to figure out how
         | to use rails' abstractions (like `has_one :posts`) without
         | needing to understand their implementation.
         | 
         | On the other hand, the average production codebase should
         | minimize their use of metaprogramming. When I don't understand
         | how Joe's `Whatsit` interface works, I'm much more likely to
         | need to dig into Joe's code to understand how to use that
         | abstraction. If I have to understand Joe's deep magic every
         | time I do that, it's a net loss.
        
           | hiharryhere wrote:
           | It's not even has_one :posts, it's has_one :post because of
           | even more rails pluralization magic :)
           | 
           | Agree with everything you said
        
             | rezonant wrote:
             | could be a model called Posts and plural is "postses" :-)
             | 
             | (disclaimer: I do rails all day)
        
         | cutler wrote:
         | Try Clojure. It takes metaprogramming to a level higher than
         | Ruby's version.
        
         | kubectl_h wrote:
         | I've worked with Ruby for over fifteen years off and on and the
         | last seven exclusively -- in a large codebase with a fair
         | amount of metaprogramming. We've onboarded engineers, junior
         | and senior, who previously have never used Ruby and it's been
         | interesting to see who does and doesn't have a hard time with
         | it. It doesn't seem to match overall experience and skill
         | level. It's more of a sense that people with patience and a
         | kind outcome oriented approach (over fixating on why something
         | is done a certain way) will have an easier time unwinding the
         | complexity.
         | 
         | One thing I've noticed, and this is something that seems to
         | bother non-Ruby engineers, is the people that flourish in a
         | complex Ruby application prefer to read code over
         | documentation.
        
       ___________________________________________________________________
       (page generated 2023-07-27 23:00 UTC)