3 ms·
Ruby is a great language if you don't go hog wild with extreme OO ideas and metaprogramming. Unfortunately, in my experience, it's way more common to go hog wi
by ravenstine 5y ago
Ruby is a great language if you don't go hog wild with extreme OO ideas and metaprogramming. Unfortunately, in my experience, it's way more common to go hog wild than to just do things in a straight forward way.
Before y'all throw tomatoes at me, allow me to make things more confusing...
The problem with elegance is that it is mostly about being clever, but cleverness is often a tradeoff for being cryptic and hard to follow for those who don't have context or understanding. Because it is an abstraction, elegance in the form of things like metaprogramming and inheritance hierarchies make the underlying ideas more difficult to understand, not less.
Many programmers, including myself at one time, confused the idea of making something abstract as making said thing simpler, but more often than not it is the underlying details that are most important to be able to read and understand as a sequence of instructions and you are abstracting at the wrong level. Languages like Ruby are already so abstract that even just a level of abstraction above what it already provides can make code murky, resulting in lots of "thinginess" but not "this does this, and then this, in order to result in this".
I'm not singling out Ruby, BTW, but the topic of the article just happens to be especially vulnerable to the issues that caused me to lose interest in it and OOP in general.
I won't go into inheritance other than that I've realized that it's a terrible idea most of the time and that a growing number of programmers agree. Over the years things like Rails have added concepts that lean more into composition, but every single Rails project I've ever worked on was a mess of countless levels of inheritance that makes it difficult to know where behavior is coming from (which is ironic in a way).
This isn't necessarily a failure of Ruby but rather its community since countless other languages implement inheritance. There's something about Ruby that encourages overuse of inheritance and so many projects suffer from the pitfalls of it whether the developers are willing to admit it or not.
Speaking of the community, I really don't understand the amount of effort they go through to avoid documenting anything. I'm not talking about the language, frameworks, or libraries, since they generally provide great API documentation, but if you are reading Ruby code you are far less likely to find inline documentation or meaningful readme files than in other languages. Strangely, after having used the Ruby language for 8+ years, colleagues still discourage me from adding comments here or there to provide context around why something works the way it does. In contrast, it's rare that I'm ever told not to add inline documentation to JavaScript code by other JavaScript devs. It does happen, but I've really only had that experience one time in my career.
Ruby developers buy this line that "Ruby is so expressive that you don't need to write documentation, and the tests will describe anything else." That sounds wonderful but, frankly, I'm not a computer. I don't live and breathe code, and I'm not interested in modeling MRI in my head so I can interpret Ruby code. Even if I did, I doubt it could actually communicate contextual ideas in a meaningful way because that's not what computer languages are designed for, because computers don't understand anything. When you throw in metaprogramming and other dangerous ideas, the "documentation" you are writing effectively turns into a Choose Your Own Adventure book where every page has a 6 line paragraph that rarely finishes a full thought and makes you jump to random pages in the book.
I used to not trust the notion that Ruby is slow, and I still think that perspective is overstated, but not in the way a lot of people think. The vast majority of Ruby projects I've worked were much slower than they needed to be and, again, it usually came down to the community not being interested in how to write code in a performant way and understand which parts of the interpreter and standard library are faster or slower. The barrier of entry to Ruby is so low that a big chunk of brand new code is written by junior developers, which is insane but also extremely economical. My first Ruby job paid me $40k (in SoCal of all places!) and although I did achieve some pretty interesting things, I also wrote a lot of crappy code that the businesses didn't care was bad. And they won't ever care until they can't hire anyone to fix the mistakes that were also piled on top of my own, in which case it will all be rewritten with PHP and React. It's astounding just how slow a Rails project can get, not just when it serves HTTP requests but in just starting up the server. JavaScript and Node has its definite faults when it comes to over-reliance on 3rd party packages, but the Ruby world too has a problem with over-reliance on packages; it's just fewer people care because Ruby's package management has advantages over the wild west of NPM. It seems that with every `rails-` gem that gets installed, the speed of everything decreases exponentially and no one bothers keeping track of it. Rather than waste time working towards 100% code-coverage, track performance* and you will save countless dollars in human hours. Ruby seems like a great way for small companies to whip out something great, but has anyone actually figured out whether less time, money, and energy is expended on Ruby projects than on alternatives? Ruby sells itself as being good for productivity, but if it's more often slower than projects that use other languages and frameworks (which is true in my experience), then it's not living up to the promise that people are still buying into.
Ruby has an awesome syntax, thus I wish there was a radical shift in Ruby, perhaps a fork, where the great parts of the language that make it especially readable and expressive could be kept while metaprogramming be made highly limited and inheritance impossible. Basically, it should get rid of the things that drag it down in terms of performance and readability and focus on what other languages managed to do right.
EDIT: Other thoughts...
Oh, and it should be made possible to declare and import modules without automagically bringing them into the global scope unless you `require` them under your own module scope. That way programmers can just write functions and not feel the need to add them under a named module or class scope.
Speaking of, the distinction of a method, proc, and lambda should go away and just be replaced with functions that have a binding. They add nothing but confusion, and I doubt most Ruby programmers even know the difference or why it is that they call everything "methods" while other languages have "functions" that can both be methods and assigned to local variables. And yeah, you can kind of do that with procs, but procs really suck.
Implicit returns are also... yeah, kinda not worth it and makes things less clear IMO. Again, I actually like a lot about Ruby, but I've never gotten used to implicit returns. I really don't think it adds anything useful to the language and just makes things more confusing for people coming from other languages.
- dragonwriter 5y ago> Ruby has an awesome syntax, thus I wish there was a radical shift in Ruby, perhaps a fork, where the great parts of the language that make it especially readable and expressive could be kept while metaprogramming be made highly limited and inheritance impossible. Uh, the features you want to be kept and those you want to be limited are the same features (or, at least, the latter are a key component of the former), so that’s not going to happen. Metaprogramming and inheritance are (key to, not all of) the features that make Ruby especially readable and expressive.
- ravenstine 5y agoIt's all a matter of opinion, but I argue that those are not what make Ruby expressive. What makes Ruby expressive to me is that it relies more heavily on English language than other languages that make heavy use of symbols and overly concise naming conventions. The symbols it does use (and I don't mean the Symbol class) get out of the way when you don't need them, meaning you can often get away not using curlies or parens, which may result in code that is easier for the human eye to parse (w/ syntax highlighting) and makes it simple to write DSL-like code and APIs without going down the full metaprogramming rabbit hole. Languages that are more C-derived don't have such affordances. Conveniences for creating ranges, calculating time, having array/enumerable operators, etc., are all highly beneficial. Ruby stands out in those ways without things like metaprogramming. It's the parts that get out of the way that are great, whilst metaprogramming can easily end up interfering with anyone who didn't write it. There are certain exceptions, but they are usually well tested libraries that get a lot of time and attention. The metaprogrammed DSL one guy wrote, who left the company before you showed up, can have flaws that take hours to flesh out.