-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefer method invocation over instance variables #331
Prefer method invocation over instance variables #331
Conversation
I don't feel strongly about this, but I think there are reasons not to do this:
I follow the style of whichever code base I'm participating in, but when I start projects from scratch, I avoid unnecessary |
I almost never (ever) have seen a usage of attribute reader, for anything other than returning the instance variable. I'm a fan of instance variables, |
@gylaz @jferris, to address some of your points:
There seems to be some disagreement with this: https://bugs.ruby-lang.org/issues/10967 Tangentially related: we promote the use of protected (over private) for
I felt similarly, years ago, about using
and
I guess my thought is that, if you're referring to a value, it doesn't matter what it's doing other than returning what it's required to. Referencing an instance variable provides unnecessary specificity that the internals of the object likely don't care about. |
I agree. I've been following this guideline in my projects for the last year and I've really enjoyed it. It makes me less concerned about what something is and instead I worry about the method I want. I'm 👍 on this. |
Eventually, yes. But at first, when I see a If we want to follow the spirit of YAGNI, instance variables, or direct variable access, would be what we should go with. Using attribute readers requires more code, for what quantifiable, proved value? |
I'm 👍 on this, but I also don't care that strongly and am not sure we need to have a guideline. We discussed this in a Boston dev discussion eons ago and the room was split 50/50.
My $0.02 is that they are worth it for typo protection alone. I'd love to see everyone use |
I would argue that the error produced by mistyping the instance variable is just as helpful as
When I'm on a project that uses |
Huh - is that name error new? |
A quick sanity check from the peanut gallery... This is Ruby 2.2.1: class Cat
attr_reader :name
def initialize(name)
@name = name
end
def speak
puts "Hello my name is #{@nmae}"
end
def speak_again
puts "Hello my name is #{nmae}"
end
def speak_once_more
puts "Hello my name is #{self.nmae}"
end
end
|
I was wrong, mistyping an instance var results in |
Syntax-wise, calling methods is more flexible than accessing instance variables. When using instance variables, transitioning to using a local, a constant or calling method requires updating every reference to the instance variable. Changing what a method refers to is a one line change. This is in line with depending on behavior instead of data. I can't remember feeling the pain of using an instance variable instead of calling a method, though. |
c10457a
to
72f0ad3
Compare
I am in favor. |
I like this too. |
I'm against this rule. When you are seeing When you see Making a private accessor feels like a layer of abstraction that you don't really need. Writing |
I'm in favor, and I've been doing this for a while on all my projects. I prefer not to mutate my instance variables. Also, the errors for typos are great. |
It's good to remember that Using
This is probably the best argument for |
This is why I'm 👍 this. |
I am 👍 on this because I find it easier to determine where the assignment occurs (assuming you're using an class Foo
attr_reader :bar
def one
bar.one
end
def two
@bar = Two.new
end
def three
bar.three + 8998
end
end vs. class Foo
def one
@bar.one
end
def two
@bar = Two.new
end
def three
@bar.three + 8998
end
end That's not a great example, but I recently ran into a situation where an ivar was called from a controller action, and it was difficult to tell where it was assigned. In order to find where it had been assigned, I had to read through every method that was called prior. It turns out it was assigned in a |
+1 for "typo returns NoMethodError" reason |
Given how the tide turns on this PR, I think I'm okay of being overruled. Note that you have to wait until Ruby 2.3 to be out before you could use |
This PR has been open for a staggering amount of time. Is there anything we can do to reach a consensus, or have it been reached? |
How about no guideline, and let the project members decide? |
I have created a poll to settle this matter: https://docs.google.com/a/thoughtbot.com/forms/d/1P5u_6tbN18Phl8bKo0Bh0EM5wmPIzT-j805zIn0xYFQ/viewform |
@jferris did your poll reveal compelling new data? @joshuaclayton how are you feeling on this after so long? |
I still feel strongly that this is the right route to go down:
Looks like 2/3 of the responses (out of 25 respondents) prefer this as a guideline. |
There were no votes for using Also, the private/protected issue discussed earlier in the pull request has been resolved in Ruby 2.3, so Ruby itself no longer has any opinion here. I think this is good to merge. |
Referring to instance variables in various methods within a class violates the single level of abstraction principle; it applies a specificity that methods using this information need no context of. By preferring method invocation over instance variables, it provides the developer the ability to refer to a concept which can be defined by a method via direct definition or via `attr`, `attr_reader`, or `attr_accessor`.
72f0ad3
to
f6b9866
Compare
Referring to instance variables in various methods within a class
violates the single level of abstraction principle; it applies a
specificity that methods using this information need no context of.
By preferring method invocation over instance variables, it provides the
developer the ability to refer to a concept which can be defined by a
method via direct definition or via
attr
,attr_reader
, orattr_accessor
.