Torbjörn
Torbjörn

Reputation: 5800

Is it good practice having local variables starting with underscore?

I'm just getting into Ruby and come from the Java and C/C++ environment.

While coding a first little project in Ruby, I somehow got used to let all local variables start with an underscore. I guess my main motivation for this was a better readability and distinction from method calls.

As in principle there are only three types of variables ($global, @instance and local), the vast majority of variables start with an underscore. I'm not really sure, whether this is good or bad. Besides, in a lot other languages, the underscore would be substituted to some other character.

Is there somehow a best practice concerning variable naming beside the usual CamelCase and/or underscore separated? What are the habits of the professional "rubyists"? Have I overlooked some general Ruby conventions, when I chose the leading underscore?


edit
Thanks to all answers and suggestions. It helped me a lot.


Short Summary of Answers and Comments below
(for the short-on-time visitor)

Leading underscores go with:

All other local variables without leading underscores, as programmers coming from e.g. JavaScript might get confused about intended behaviour of the variables.

For visual separation between variable names and method calls, forcing oneself to use "(" brackets ")" with all method calls might increase readability significantly.

Upvotes: 14

Views: 13803

Answers (4)

Jim Stewart
Jim Stewart

Reputation: 17323

Existing answers to this question are now a few years old, and conventions have changed. You should only ever use a leading underscore (_some_param), or a standalone underscore (_), to indicate that you don't care about the value. The rubocop style linting tool will carp about a "useless assignment" if you assign a variable but don't use it, but it will ignore variables with a leading underscore. This allows you to expressly indicate that you don't care about the value and don't intend to use it.

Here's a somewhat-contrived example use-case in an RSpec context:

describe 'login' do
  let(:user) { FactoryGirl.create(:user, login: 'bob') }
  it 'must be unique' do
    _user1 = user
    user2 = User.new login: 'bob'
    expect(user2.valid?).to be_false
  end
end

Here we're indicating that our user helper has a side-effect and returns something, but we don't care about it. You could also just skip the assignment entirely, but seeing a bare user on a line by itself looks odd and doesn't reveal the intention as clearly:

describe 'login' do
  let(:user) { FactoryGirl.create(:user, login: 'bob') }
  it 'must be unique' do
    user
    user2 = User.new login: 'bob'
    expect(user2.valid?).to be_false
  end
end

Other scenarios include ignoring values in iterators, or overriding a method where you want to keep the original method signature but don't care about some of the values:

def greet(name, _title)
  puts "Hi, #{name}!"
end

Upvotes: 16

bioneuralnet
bioneuralnet

Reputation: 5301

Nothing wrong with your idea. But if I was having trouble distinguishing local vars from method calls, I would probably just force myself to always use ()'s on methods. (My team at work has discussed making this part of our coding standards).

a = thing # var
b = thing() # method

The possible advantage to this is readability to others. Someone may wonder at your leading _'s, but using ()'s on all method calls should be clear to everyone.

Upvotes: 2

Matt
Matt

Reputation: 10564

In my experience, underscore-prefixed variables in Ruby are much like underscore-prefixed variables in JavaScript: a "don't touch" flag. More specifically, they are used when the implementer is doing something that really is not supposed to be understood as a part of the object, or shouldn't be thought of as the conceptual interface of the object.

This is more clear in the JavaScript world, where somebody is emulating "private" by prefixing a variable with an underscore. They are encoding that there's part of the object that's under the hood and can be ignored when looking at the object from the outside.

In Ruby, I've only really seen this with things like a cache or a singleton instance - the kind of thing that should be invisible to consumers of your object. Non-underscored variables are things that people using your object might be interested to know are there.

In any case, they seem fairly rare, and I would avoid them unless you want to send a signal to the next guy that's coming along that there's some extra magic or voodoo happening.

As far as making a distinction for method calls, if you're worried that there can be confusion between a method and a local variable, I would call the method on self to clarify. For instance:

def foo
    ...
end

def some_method
    foo # method
    bar # variable
end

If this seems unclear for whatever reason, you can clarify with

def some_method
    self.foo
    bar
end

Upvotes: 3

Batkins
Batkins

Reputation: 5706

Seeing as how instance variables have the @ sign in front of them, and global variables have the $ sign in front of them already in ruby, it is probably unnecessary to put an underscore character in front of the variable names. That being said, I don't think it is a bad practice necessarily. If it helps you to read or write your code in Ruby, then you should use it.

I have sometimes seen Ruby code where an argument for an instance method on a class has an underscore in front of it. Such as:

def my_method(_argument1)
  # do something
end

And I think that when you are dealing with a class that may have it's own attributes, like a model file in rails, for instance, this can be helpful so that you know you are dealing with a variable that has been passed into the method as opposed to one of the attributes that belongs to the class/model.

Upvotes: 2

Related Questions