To create a new object in Ruby you invoke the
new class method like so:
c = Car.new("Toyota")
Naturally you think the constructor would be defined in a method called
new, right? Or just maybe a method called
Car like in Java? But no, instead it has to be called
initialize like this:
class Car def initialize(make) @make = make end end
Would this have been so hard?
class Car def new(make) @make = make end end
2. Weak typing
As a library vendor, it scares the bejeezus out of me that anyone can pass anything to my methods and I’m expected to handle it. It’s like walking into McDonalds and ordering a Big Mac, and instead getting a Tofu burger; not very appetizing. Ruby’s thrown out the one piece of precondition checking most languages give you for free.
3. Automatic returns
Didn’t C teach us that unexpected results were confusing? This is Ruby’s equivalent of C’s
a = b + a = c;. Returns should be explicit. An explicit return is not hard to write, and it’s a lot easier to read and understand. Reducing finger typing and at the expense of increasing brain confusion is not a wise tradeoff. Languages should be concise only in so far as that improves clarity. When compactness comes at the expense of clarity, it’s a bad thing.
4. Global variables
Didn’t somebody tell me Ruby was an object-oriented language?
Do we have to copy C’s most ungrammatical, pointless method names?
6. Zero-based arrays
C arrays began at zero to match memory addressing. In a weakly typed scripting language, there’s exactly no reason to do this. There hasn’t been for decades. Can’t we please start the arrays at 1 where God intended? Hasn’t anyone read Numerical Recipes? Aren’t we tired of fencepost errors yet?
Sorry. “elsif” is not a word in the English language, and it shouldn’t have been one in Ruby. Would typing one extra letter have been so onerous?
Global variables suck. Did I say that already? Global variables you didn’t actually create and that pop up out of nowhere suck even worse. And global variables whose names are indistinguishable from line noise suck still more. Java’s verbose, but that verbosity is in the service of legibility. Ruby’s compactness all too often serves only to obfuscate.
9. Methods are public by default
Minimal interfaces to classes are important. The less a class promises, the easier it is to change, optimize, fix, and otherwise improve. Furthermore, the easier it is to learn and understand. Everything that can be private should be private.
Now of course you do need public methods. Not everything can be private. However this shouldn’t be the default. Marking a method public decreases the flexibility and increases the learning curve of the class. It should require an explicit decision from the programmer to do this. Ruby gets this exactly backwards. A programmer just banging out Ruby code is likely to create a class with nothing-but-public-members, without even thinking about it. That’s a bad thing.
10. No package access or friend functions.
There’s no access in-between public and private. All too often different classes in the same library/application/codebase need more detailed access to their other parts than the general public should have. Ruby provides no way to manage this.
I could go on (and I probably will) but that’s a nice round number of hates for now. I’m also keeping a list of things I love about Ruby as I learn the language. However, the things I hate hit 10 before the things I love. That’s not a good sign.