Ruby 101: Naming Conventions 28
UPDATE: Fixed some typos in the DialUpModem example code.
Ruby enforces certain coding conventions, while others are considered to be community-accepted idiomatic Ruby. I’d like to cover them here.
I can’t cover everything in one blog post. Instead, I’ll review the more egregious cases that seem to pop up on the Ruby and Rails mailing lists. Most of these seem to come from our Java friends who are now using Ruby without regard to learning Ruby style. .NET developers are prone to the same criminal activities, so I hope this will help both Java and .NET developers that are new to Rails.
Today all of these situations involve method names.
lowercase_and_underscored
Suppose we have a class DialUpModem with a method that will terminate the connection.
Please don’t do this, you formerly-Java people:
def hangUp()
nor this, formerly-.NET people:
def HangUp()
Instead, do this, all you seen-the-light-and-now-very-cool people:
def hang_up
Notice two things here:
- everything is in lowercase
- underscores separate words
- don’t append empty parentheses if there are no parameters
Ok, that was three things, not two, just to see if you’re awake.
Methods that return boolean values
Don’t do this, formerly-Java people:
def isOnline()
nor this, formerly-.NET people:
def IsOnline()
Instead, do this, all you seen-the-light-and-now-very-cool people:
def online?
See? We don’t use the word “is” to start a method name. Instead, the Ruby language recommends that you use a question mark at the end of a method name to indicate that it will return a boolean value. (It’s not required by the language, it’s just a convention you should follow.)
By the way, you can still take parameters if you need to:
def high_speed?(min_speed = 19200)
Properties Are For Monopoly Players
...not Ruby programmers. So puleeeze don’t do this:
class DialUpModem
def get_speed
return @speed
end
def set_speed(value)
@speed = value
end
end
Don’t use getters and setters when there’s no logic involved. Do this:
class DialUpModem
attr_accessor :speed
end
Done. Nice. Clean. Simple.
If you do have logic involved, you can still override the getter or setter as appropriate:
class DialUpModem
attr_accessor :speed
def speed=(value)
# Limit the speed to 19200 baud.
if new_speed > 19200
@speed = 19200
else
@speed = value
end
end
end
Notice the ’=’ sign at the end of the method name – that’s how you define a “setter” method in Ruby.
If/Else Statements Are Suspicious
I know I said this post was just about method names, but now that you’ve made it this far I can’t resist one more Ruby tip.
See that setter method we just wrote? That is some very, very ugly Ruby code.
Learn instead to wield the power of the Enumerable module:
def speed=(value)
@speed = [value, 19200].min
end
How to Learn Idiomatic Ruby
Read the good Ruby books by the good authors: David A. Black, Dave Thomas, Hal Fulton, and others. And read as much Ruby code as you can, so you can start to become assimilated into the Ruby style of programming.




DialUpModem should be this instead, no?
class DialUpModem
end
p.s, I think you should go further into the "Enumerable module", that'd be very beneficial with that snippet of syntax. Why that works, why that is better, etc.
Thanks !
That last example should probably have 'min' instead of 'max', right?
Daniel and Jorg: Thanks for spotting those! I've updated the code. Glad to see someone is paying attention (obviously not the author :-).
My problem is that I take Ruby idioms back to C#! Great post that I will certainly share with my co-workers. :)
I have just recently found your blog and absolutely love the posts. Thank you, thank you. I am still .NET programming but can't wait to try these things in Ruby and it is a great help to see such clear examples.
Thanks for the tips!
I just took a look at ruby scripts I wrote 2 years ago: My motto was "f**k conventions!" back then. I wish I knew a little bit more at that time!
BTW, you can replace this attraccessor by an attrreader now that speed= has been defined!
Thanks, I'm not used to read ruby code, and it's sometimes perturbing.
do you really see: @speed = [value, 19200].min
used widely in Ruby source code? Could you please supply some references.
I see that as allocating 2 chunks of memory and calling a function. Rather than just dispatching across 4 (?) methods (I believe that Ruby if / else really get converted into method calls ... or did I just suddenly get confused with various comparisons of Ruby to SmallTalk there...)
I guess my point being is I see that particular idiom as more wasteful than "simple" business logic, when using such a contrived/simple example as comparing 2 values.
Good post nonetheless :]
@dqurba
If you don't like creating an array for 2 elements:
((value+19200)+(value-19200).abs)/2
will do!
why not?
@speed == (value > 19200) ? 19200 : value
one liner, easy to read, and still fast.
@devnull
I do that in php all the time in my return statements ... and sometimes in my ruby code. like I said I just hadn't seen the packing of values into an array for finding the min of 2 values. Maybe the min of 30 or 40 values via a collect() [or some other way to gather the data into 1 array] I would do so I could then call min() ... but not 2 items :)
I blogged about using [x, y].min to limit a value at http://jeronrails.blogspot.com/2007/08/lesser-of-two-weebles.html. (I referred to it as Array#min, but Arrays are Enumerable and it is an Array in this case.)
It's a terse idiom, and if you're concerned about the performance you must not have a database or anything else that consumes resources orders of magnitude greater. Consider yourself lucky, otherwise don't optimize at this level unless you really need to.
@speed == (value > 19200) ? 19200 : value
This contains duplication (and it would still contain duplication if the literals were replaced by an identifier) while the array min example doesn't. Also the latter is more expressive. The above code is still an if-statement. The array min example explicitly says it's looking for the smallest of two values (the definition of min).
And yes, anyone who cares or even thinks about the speed implications (as opposed to the readability) is probably using the wrong language.
///ark
Nice tips. Thanks
Love your 101 articles...thanks Jeff !
Great article - enjoying the entire 101 series. Just a quick thought - it would be really slick if you could tag the 101 articles with "101" (or whatever) so that they can be more easily read as a group.
Jeremy Weiskotten, Mark Wilden: You might want to re-think the comments about speed. ;) Compound habits like this, and Ruby will quickly become more taxing than most database calls you'll be making, so this wasteful idiom should die...
And what happens when you have [nil, 19200].min ? Or ['bob', 19200].min ? Do you really want to see "ArgumentError: comparison of Fixnum with nil failed" when you call #speed= ?
@speed = (value.to_i > 19200) ? 19200 : value
Simple. And as PragProg said: Readability first. Focusing on repeated character patterns is missing the point of DRY. The following alternative is perfectly DRY in every sense of the original intent:
@speed = (value.toi > MAXSPEED) ? MAX_SPEED : value
Please, everybody, remember the rules of designing and coding for performance...
in-the-large -- make a reasonably efficient big-picture architecture, with at least some idea of performance weaknesses that are hard to fix at first, but can be handled later
in-the-small -- code for clarity and perspicacity, with very little attention to small, local efficiency (that is, only where you know for sure it is very important, like at the innermost core of your most crucial loop -- maybe)
afterwards, go back and make adjustments in both the-large and the-small based on actual experience, in priority order based an actual measurements, profiling, points with obvious observable performance impact, etc.
That way, you don't waste time and ruin code making things efficient that will never make a discernible runtime difference.
(I'm sure there's a pithy saying to summarize all this -- but I call it "smart optimization".)
Please, everybody, remember the rules of designing and coding for performance...
in-the-large -- make a reasonably efficient big-picture architecture, with at least some idea of performance weaknesses that are hard to fix at first, but can be handled later. Remember, it's much more important to use, say, an O(n*log(n)) algorithm vs an O(n^2)) one than to sweat a small improvement in the constant factor.
in-the-small -- code for clarity and perspicacity, with very little attention to small, local efficiency (that is, only where you know for sure it is very important, like at the innermost core of your most crucial loop -- maybe)
afterwards, go back and make adjustments in both the-large and the-small based on actual experience, in priority order based an actual measurements, profiling, points with obvious observable performance impact, etc.
That way, you don't waste time and ruin code making things efficient that will never make a discernible runtime difference.
(I'm sure there's a pithy saying to summarize all this -- but I call it "smart optimization".)
There are lots of good examples how a smart person can make those credit cards work for him. I hope to do the same by applying for a credit card at
do balance transfers lower your credit rating
Because of our necessary ignorance of the conditions, our a priori concepts, in natural theology, would thereby be made to contradict the Categories; in the study of the transcendental unity of apperception, the transcendental unity of apperception (and let us suppose that this is true) is the key to understanding the transcendental objects in space and time.
The epoche calls our attention to the fact that experiences, where this is still wanting, are unified synthetically, by reconciling with noematic descriptions.
Hi Jeff, Thanks of your tip. It is simple and clean.
Shouldn’t be the new_speed be value instead?
hmmm,i would lyk to use in my application
I’ve found this article when I was looking for naming conventions for Ruby. It’s so difficult to find some documentation (even official doc.), thanks so much for this article.
I’ve noticed that in rudy-doc.org, it’s written “def getTax(amount)”. It it correct? Why do you write methods in lowercase with underscores? (http://www.ruby-doc.org/docs/ProgrammingRuby/)
Thanks for your work :)
Though you cover quite basic facts, this should be crucial for newbie Ruby developer, since code convention predefines code readability in future.
Though you cover quite basic facts, this should be crucial for newbie Ruby developer, since code convention predefines code readability in future.