Duncan Mac-Vicar P.


Encapsulation and don’t repeat yourself

with 2 comments

Richard Moore comment on Access Anxiety explains why Encapsulation is a good thing. I think both are missing the point. Nobody doubts that encapsulation is a good thing, and Michael Feathers tries to present ruby way as a more “relaxed” thing.

The author was comparing the ‘ruby style’ of direct access to member variables with the getter/setter pattern common in Java code

So what is the ruby style really?

The annoying thing about java setters is that they are functions. So you either start with them (which is overkill for simple things) or don’t use them and then you are lost when you want to add things like Richard showed.

Ruby on the other hand, makes it easy, because you can’t expose member variables, but you can very easily create default accessors.

Michael Feathers example is wrong. Usually you start by actually offering a simple default accessor.

class GlazeObject
  attr_accessor :store, :formatter

  def initialize
    @store = DefaultStore.new
    @formatter = DefaultFormatter.new
  end
end

Now, if you need something more special, like Richard example:

public void setFormatter(Formatter formatter) {
        this.formatter = formatter;
        this.expensive = doCalculation(formatter);
    }

You can just remove attr_accessor :formatter and add to the class:

class GlazeObject
  def formatter
    return @formatter
  end

  def formatter=(f)
    @formatter = f;
     @expensive = doCalculation(f);
  end
end

What is the difference? In ruby, for client code consuming this class, you always see obj.formatter for both cases. In java you have to start from the beginning copy-pasting repetitive accessor code if you don’t want to start changing obj.formatter to obj.getFormatter() and obj.formater = something to obj.setFormatter(something).

C# has a similar feature, called properties.

public class Person
{
  private int _age; 
  public int age
  {
   get
   {
     return _age;
   }
   set
   {
     _age = value;
   }
  }
} 

No matter if we start with a public variable called age, we can move it to setters and getters (which are the providers of encapsulation without having to change the operation mode from variables to functions.

Written by duncan

December 21st, 2007 at 10:28 am

Posted in uncategorized

Tagged with , ,

2 Responses to 'Encapsulation and don’t repeat yourself'

Subscribe to comments with RSS or TrackBack to 'Encapsulation and don’t repeat yourself'.

  1. Having default accessors seems like a nice technique. Do they extend to allowing you to add additional parameters? eg. To migrate to something like setFormatter( Formatter, bool deep = true );?

    Richard Moore

    21 Dec 07 at 10:52 am

  2. Well, I don’t think it is possible in that way.

    Ruby does the trick because an assignment on a object member is done by calling the method member= on the object.

    attr_accessor is just a function which generates the most simple case on which a member variable of the same name is assigned.

    Even if you can define

    def member=(a,b) # do something end

    there is no way to call this using the assignment syntax.

    You could of course do obj.send and send the method name and parameters to reach that method.

    What you can actually do, is define the setter to accept an array of arguments:

    require ‘pp’

    class Foo def bah=(*opts) pp *opts end end

    f = Foo.new f.bah = 1 f.bah = 1, { :param => 1}

    In the first case, you will get an integer, in the second case, an array where the first element is the integer, and the second element is a hash with the options.

    My experience with methods taking bool flags to modify behavior is not good :-(

    duncan

    22 Dec 07 at 8:25 pm

Leave a Reply