I recently read Crockford's book "Javascript: The Good Parts" and one of the underlying premises was that programming languages can have bad sets of features which programmers should avoid.

I'm a Rubyist and whilst I love the language there's always value in getting perspective. So, what do you see as the worst feature (e.g. methods, classes, practices) in Ruby? My intention here is not to start an argument about the merits of the language itself or its speed and so on. Rather I'd prefer a discussion of what features you consider dangerous / troublesome / painful to use, based on past experiences.

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. If this question can be reworded to fit the rules in the help center, please edit the question.

This question came from our site for professional and enthusiast programmers.

1

I've never been a fan of having to use the word "end", and then the mixture of that with "{" and "}" gets even more annoying. It makes me appreciate either Python-style syntax or straight up { & }'s. Although one could argue back and forth on this, and ultimately it has a lot to do with personal preference. I heard someone say that Ruby takes the ugliest parts of Python and Perl and puts them together. I am enjoying learning Ruby, though.
– Mark NenadovMar 26 '11 at 11:40

I actually quite like this question and would be looking forward to answers, but nevertheless voted to close it. I don't think it's a good fit for Stack Overflow (due to potentially being too subjective/argumentative, open-ended, etc.).
– stakxMar 26 '11 at 11:41

I think it's worth discussing as it could illuminate dangerous practices to avoid. I see your point though and edited the question to be more narrow.
– Jack KinsellaMar 26 '11 at 11:44

8 Answers
8

The very things I find ugly in Ruby are what make amazing Ruby software like RSpec possible, and that Python could never have (given the current implementation).

While he talks a lot about Python in particular, he touches on a lot of stuff that's just weird in Ruby. One of the big overarching subjects is monkey patching.

Ruby objects (unlike objects in some other object-oriented languages) can be individually modified. You can always add methods on a per object basis. In Ruby, the behavior or capabilities of an object can deviate from those supplied by its class.

While this provides a lot of flexibility and powers some of Ruby's most popular and complicated gems, it can bite you in the butt if you're trying to debug an issue without realizing that some library somewhere has modified a core method.

I think the worst feature is open classes which allow you to globally change the behavior of all current and future instances of the changed class.

The problematic part of this feature is, that theses (global) changes happen during runtime when the Ruby interpreter comes across the definition, which might be long after you already instantiated a couple of objects which now change their behavior all of a sudden.

In a large code base this can result in very, very hard to find bugs - especially as this gets compounded by Ruby's weak (as compared e.g. to the CLR or JVM) debugging story and use of other features (e.g. eval) in this context can make it quite hard to find the location where this global change occurred. i.e. if you already reached the point where you suspect the 'right' class causing the trouble! In my experience you usually start out with a wild goose chase, as the problems start to surface at an object using the real culprit.

So the best thing would be, either to stop using open classes (#extend and putting the changes in a Module is IMHO much safer, easier to understand and better to test) or if it can't be avoided to:

only extend classes with new behavior (i.e. not overriding existing behavior)

have a defined place in the source code tree, where all extensions using open classes have to be placed

do not use #eval and friends to create open classes

put all usages of open classes on a big visible chart, where all developers can see them - and make clear that any changes on them are 'architectural decisions' affecting the whole code base (which they do) and not the place for quick hacks useful for your current task

Biggest reason I don't use Ruby: It's slower than molasses in January at the North Pole during an ice age. Benchmarking languages is an inexact science, but Ruby appears drastically slower than even JavaScript and Python.

what was the application you developed for which ruby was too slow ? I mean, I believe you when you say it is slow, but how did it stop you from reaching your goal ?
– DavidMar 28 '11 at 11:20

1

I think Ruby is great when you want to make something like a prototype and want it done quickly, something that isn't huge and won't be doing massive number crunching. If you expect to be chewing a lot of CPU cycles constantly, any good programmer knows to use something like C or C++.
– Jeff WellingMar 28 '11 at 11:33

1

@David: I would consider using Ruby for simple DNA sequence processing code, but I don't because Python fills a similar niche, has similar features and is much faster. If I'm willing to go lower level, D is even faster and still convenient.
– dsimchaMar 29 '11 at 0:58

1

@Jeff: Agreed, but C and C++ are a pain to write in. The point of high-level languages like Ruby is to avoid dealing with this pain as much as possible. The slower they are, the less well they fulfill this goal. Ruby is slow even for a high-level dynamic language. That and NumPy/SciPy are why I use Python instead when I need a high-level dynamic language.
– dsimchaMar 29 '11 at 1:00

The fact that the database logic gives every single table an auto_increment primary key, including tables that don't need them and shouldn't have them.

The fact that compound keys aren't supported at all.

For just plain Ruby my gripe would be the same as for any language that trades safety for expressiveness; it's easy to do a lot with just a little code, but it's just as easy to make a huge mess with any amount of code.

Please see my edits as I've narrowed the scope of the question. I'll start another parallel one for Rails if this question with edits is approved.
– Jack KinsellaMar 26 '11 at 11:48

1

Sorry, but you're mistaken, not every table in a Rails app is required to have an auto_increment id, notably join tables for has_and_belongs_to_many relationships are suggested to explicitly NOT have an id column.
– Brett BenderMar 26 '11 at 13:38

@Brett - Are those relatively new additions? When I was playing with it back in early 2008 it definitely did not have those features. In any case, it's great that they're available now.
– arothMar 26 '11 at 13:49

1

@aroth: I'm not sure that everyone else would consider "relatively new" to mean "within the last three years" :-)
– nickgrimMar 26 '11 at 14:33

There's an alternative to Rails' ActiveRecord called DataMapper, which is not as opinionated as ActiveRecord.
– Endy TjahjonoMay 4 '11 at 11:30

Ruby embraces metaprogramming (reflection, introspection), multi-paradigm programming, and dynamism at an uncommon level. It's easy to shoot yourself in the foot with power and flexibility.

Troublesome? Ruby has the ability to be extremely readable or inscruptable. I've seen code that looks like it belongs in a Bash script.

Bad Practices? Some Rubyist value cleverness over wisdom. They write and share tricks that show off their cleverness, but this creates unreadable and fragile code.

As an aside:
Javascript was a disaster by design, and "The Good Parts" book tries to extract it's hidden beauty. Perl, a language which popularized "There's More Than One Way To Do It" (that is, flexibility), has a similiar book in "Perl, Best Practices". Perl's history is one of experimentation and hard won experience, "Best Practices" represents its knowledge. Perl 6 will be, I think it's fair to say, a reboot of the language based on that knowledge and more. Ruby may suffer from similar issues.

@James and for loops...
When you do a for loop in ruby, it then calls ".each". Therefore, "for" is syntactic sugar for people more comfortable with C style loops. But as a Rubyist, you're going to use iterators like .map, .inject, .each_with_object, all the time. You'll never have to write a for loop with something like "i=0;i>6;i++" in ruby, and so you end up dropping the habit.
@andrew...
eloquent ruby doesn't endorse for loops.

Once I even got the answer "It's less key presses", which is clearly false ... :-)
– JamesMar 28 '11 at 9:38

2

Two theories: 1) Using for loops is something n00bs do. People who are programming C in Ruby. 2) Blocks are used a lot in Ruby, so using something not block-like is just extra mental effort.
– Andrew GrimmMar 28 '11 at 10:36

3

While I just started to learn Ruby, blocks are something that I really like and miss when I try to use Python. Would a for loop do the same thing? Of course, to me, this kind of style just suits my preferences more than a for loop.
– JettiMar 28 '11 at 12:50

2

@andrew To be honest, your 1st answer is exactly the kind of rubbish I got back when I've asked before. No real reason, with a subtle insult on top. @Wayne, @Jetti and @andrews 2nd answer: thanks. Fair enough then.
– JamesApr 14 '11 at 21:51

1

If you mean "enhanced" for loops (aka. for <value> in <expression> do ...) there is no difference apart from #each being in use and appearance closer to its commonly used cousins #inject, #collect, #reject etc. If you're talking about 'C' style indexed loops (aka. for int i = 0; i < whatever; ++i) the difference is, that a) "off by one" errors are impossible and b) that it makes the intention of your loop clear - #each meaning "for each element produce a side effect". A for loop requires you to read the whole loop just to get the 'gist' of its purpose.
– Alexander BattistiMay 4 '11 at 13:05