1

Something that I see in a lot of code:

class Foo
  attr_accessor :bar

  # lots of code omitted

  def baz
    'qux' if bar
  end
end

The exact form of the baz method is not too important - it's just that bar here is a reference to the getter method for the instance variable @bar, called from within the instance's class. I would favor retrieving the value from @bar explicitly. Are there any opinions on this? I've never seen anything in the ruby style guide or similar covering this. I personally find that doing the former makes it harder to read and understand, especially when classes are over several hundred lines long.

Edit:

Perhaps to illustrate what I would consider to be the awkwardness of this design, let's re-evaluate a pretty standard initialize method:

class Foo
  attr_accessor :bar, :qux

  def initialize(bar, qux)
    @bar = bar
    @qux = qux
  end
end

If we use the setter method, we cannot use bar = ? by analogy. Instead, we have:

class Foo
  attr_accessor :bar, :qux

  def initialize(bar, qux)
    self.bar = bar
    self.qux = qux
  end
end

which has lost some of the elegance of the first. We have a more flexible design in that we are now free to rewrite our setter method and do away with attr_writer. But I've just some points in style, and it feels a lot like configuration over convention rather than the converse, something that Russ Olsen has declared a design 'pattern' not just of Rails but of Ruby too.

user1706938
  • 131
  • 1
  • 9

3 Answers3

5

Accessing the attribute through the getter has the advantage of providing encapsulation. The use of an instance variable to store the value is an implementation detail in some respects. Whether that's appropriate is, of course, situational. I don't recall reading anything explicit this style issue, however.

Found https://softwareengineering.stackexchange.com/questions/181567/should-the-methods-of-a-class-call-its-own-getters-and-setters, which discusses the issue from a language-independent point of view. Also found https://www.ruby-forum.com/topic/141107, which is ruby-specific, although it doesn't break any new ground, let alone imply a Ruby standard.

Update: Just came across the following statement on page 24 of http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330/ref=sr_1_1?s=books&ie=UTF8&qid=1376760915&sr=1-1, a well-respected book on Ruby: "Hide the variables, even from the class that defines them, by wrapping them in methods." (emphasis added). It goes on to give examples of methods in the class using the accessor methods for access.

Community
  • 1
  • 1
Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • I want to contend that it's not a dup, since I'm asking what a 'rubyist' would do, and this thread does nothing to answer that question, informative as may be – user1706938 Aug 12 '13 at 14:37
  • many thanks for your response. that seems fairly definitive, then. i've seen plenty of examples of the converse happening in Ruby literature, but presumably to illustrate other points while simplifying the details. – user1706938 Aug 28 '13 at 17:35
  • your welcome. btw, if you didn't happen to notice, you might want to check out the reviews of that book on Amazon - pretty amazing. I'm about half way through it and am thoroughly enjoying it. – Peter Alfvin Aug 28 '13 at 17:48
  • funnily enough it has been on my list for some time! many thanks! – user1706938 Aug 28 '13 at 19:41
2

I would favor retrieving the value from @bar explicitly. Are there any opinions on this?

Yes, direct access is not as flexible of a design. Getters and setters can be used to transform values. That is why java programmers spend half their lives banging out do nothing setters and getters for their private variables--they want to present the setters and getters as their api, which allows them to change their code in the future to transform values on the way in or the way out without changing the api.

Then ruby came along with the neat attr_accessor method, which meant that writing do nothing setters and getters wasn't painful anymore.

Python goes one step further. In python, instance variables are public and you can directly access them, e.g.

print my_dog.age 

A java programmer writing a python program would implement get_age() and set_age() methods:

class Dog:
    def get_age(self):
        return self.age

    def set_age(self, age):
        self.age = age

The java programmer would then fly over all the towns in the land and drop leaflets describing the getter and setter methods as the api for getting and setting the age instance variable, and they would warn people not to access the instance variables directly--or else things might break.

However, python has a feature that allows programmers to eliminate getters and setters until they are actually needed to do something useful--rather than dumbly getting or setting a value. Python allows you to transform direct access to instance variables by client code into method calls. To the client it's transparent. For instance, the client code may be accessing an instance variable in a class by writing:

my_dog.age  

Python allows the writer of the class to subsequently implement a method named age(), and my_dog.age can be made to call that method instead of directly accessing the instance variable (note that in python, unlike in ruby, you can't normally call a method without the parentheses). The newly implemented age() method can then do anything it wants to the age instance variable before returning it to the client code, e.g. transform it into human years, or retrieve the age from a database.

7stud
  • 46,922
  • 14
  • 101
  • 127
1

It's actually faster to use a getter, mainly because attr_reader and attr_accessor are written in C instead of Ruby.

As someone who's been coding Ruby for a few years, I think using attr_* is much more readable. But that's probably just something I've gotten used to.

Community
  • 1
  • 1
Translunar
  • 3,739
  • 33
  • 55