Reputation: 69757
It seems to me like Ruby has a lot of syntactic flexibility, and many things may be written in several ways.
Are there any language features/syntactic sugar/coding conventions that you avoid as a Ruby programmer for clarity? I am asking about things that you choose not to use on purpose, not stuff you still have to learn.
If your answer is, "I use everything!," do you ever comment code that would be otherwise obvious if the reader knows the relevant Ruby syntax?
[I'm particularly interested in Ruby in a RoR context, but everything is welcome.]
Upvotes: 8
Views: 607
Reputation: 10676
begin nil+234 rescue '' end
above syntax is valid, but you should never use it.
Upvotes: 0
Reputation: 614
Avoid chaining too many method calls together. It is very common in Ruby to chain methods together.
user.friends.each {|friend| friend.invite_to_party}
This may seem ok, but breaks Law of Demeter:
More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:
The example above isn't perfect and a better solution would be something like this:
user.invite_friends_to_party
The example's problem isn't Ruby's fault but it is very easy to produce code that breaks Law of Demeter and makes code unreadable.
In short, avoid features that decreases code readability. It is a very important that the code you produce is easy to read.
Upvotes: 1
Reputation: 2233
First off: I'll break many of these rules if it's for a short one-off script, or a one-liner on the command line, or in irb
. But most of my time is spent in medium sized or larger scripts or applications. So:
Avoid:
class << self
code block for class methods. It's a cute trick, but no better than def self.foo
, and less readable (especially after the first page).for i in collection
: Use collection.each
instead.proc {...}
: usually lambda {...}
is better.@@foo
). They are problematic and can usually be replaced with class-level instance variables without much effort.ruby -w
. This is especially important if you are writing a gem to be used by others.else
' on a 'begin ... rescue ... end
' block. Personal preference: It's too much of an edge case and so few people even know it exists or how it works to be worth it.ObjectSpace
and GC
. You probably don't need to go there. You definitely don't want to go there.=begin
and =end
multi-line comments. Personal preference for line-wise comments. These just annoy the hell out of me.Use it, but sparingly or as a last resort (and comment it appropriately):
eval
(or class_eval
, etc) when passing in a string. There are some metaprogramming tricks you just can't do without passing in a string. And occasionally, the string version performs dramatically better (and sometimes that matters). Otherwise, I prefer to send in blocks of actual ruby code for my metaprogramming. eval can be avoided entirely for many metaprogramming tasks.$0
, $:
, $$
and other environmental variables, but even then you can limit your usage).
require "English"
.__END__
for a data-block. Excellent for a small one-file script. Unhelpful for a multi-file app.Don't use it, but don't really avoid it either:
Things I use often, that others might not care for, or I don't see often:
and
' and 'or
' keywords: they have different precedence from &&
and ||
, so you need to be careful with them. I find their different precedence to be very useful.Upvotes: 6
Reputation:
One thing I really loathe is "improper" use of {}
and do ... end
for blocks. I can't seem to find exactly where I learnt the practice myself but it is generally accepted to do {}
for single line blocks and do ... end
for multiline blocks.
Proper use:
[1, 2, 3, 4].map {|n| n * n }.inject(1) { |n,product| n * product }
or
[1, 2, 3, 4].inject do |n,product|
n = n * n
product = n * product
end
Improper use:
[1,2,3,4].map do |n| n * n end.inject(1) do |n,product| n * product end
or
[1, 2, 3, 4].inject { |n,product|
n = n * n
product = n * product
}
All of which, of course, will execute giving 576
Upvotes: 1
Reputation: 1014
This might be obvious but I generally avoid using eval if there's any alternative.
Upvotes: 6
Reputation: 1436
The for ... in ... loop. It directly compiles to obj.each (and throws a strange error message accordingly) and is totally unnecessary. I don't even see where it improves readability - if you've been around ruby for more than a week, #each should be natural.
Upvotes: 7
Reputation: 52316
The whole range of "$" globals (see Pickaxe2 pp333-336) mostly inherited from Perl, are pretty ghastly, although I have on occasion found myself using $:
instead of $LOAD_PATH.
Upvotes: 11
Reputation: 25750
I generally refrain from going overboard with monkey patching because it could lead to some maintainability and readability issues. It's a great feature if used correctly, but it's easy to get carried away.
Upvotes: 8