DEV Community

Adrian Lee
Adrian Lee

Posted on • Updated on

Ruby: Why to use private attr_reader

I was just reminded of why I use private att_reader in my code.

I know the advice is to always use an interface but a point of discussion between myself and a colleague has been why not to use an instance variable, with the argument that it is much more readable.

I have to agree with him in that with @foo it's obvious that it's an instance variable being referred to. I agree it's better than plain old foo in terms of readability.

That is about where the benefit ends however and there is a huge downside. Consider the following:

class Foo
  def initialize(some_variable) = @some_variable = some_variable
  def some_op = @some_varible
end

class BetterFoo
  def initialize(some_variable) = @some_variable = some_variable

  def some_op = some_varible

  private attr_reader :some_variable
end

puts "----"
puts Foo.new("BAR").some_op
puts "----"
puts BetterFoo.new("BAR").some_op
puts "----"
Enter fullscreen mode Exit fullscreen mode

The typo in the above is probably glaringly obvious since it's a small piece of code ... did you spot it? If not compare the output:

ruby some_variable.rb
----

----
some_variable.rb:10:in `some_op': undefined local variable or method `some_varible' for #<BetterFoo:0x00007fdba9d26090 @some_variable="BAR"> (NameError)

  def some_op = some_varible
                ^^^^^^^^^^^^
Did you mean?  some_variable
               @some_variable
    from some_variable.rb:18:in `<main>'
Enter fullscreen mode Exit fullscreen mode

Did you spot it now?

IMO the use of a private attr_reader so as to ensure the variable you are using has been initialised to a value other than nil overrides any readability argument; let's not mention that it more easily allows the interface to be changed internally in the future should the need arise. The fact that it's private makes it an implementation detail but an implementation detail that will save you a lot of time.

Top comments (0)