Ruby indentation for access modifiers and their sections

Ruby programmers are very flexible (and permissive) when talking about Ruby code indentation. Most of rubyists I know prefer to indent with two spaces instead of tabs (soft tabs in some editors). There are even some style guides and code conventions published for the language, but none of them is official and they talk too little about code indentation practices.

Things go even worse when we have to choose how to indent private, protected and public sections of classes. Programmers and projects I’ve seen so far seem to adopt different styles. I’ll try to summarize them here:

1. Indent as a new block

This is the most common pattern I see out there. Some programmers prefer to treat sections created by access modifiers as new blocks and indent them:

class MyClass

  def the_public_method
    # ...
  end

  private

    def first_private_method
      # ...
    end

    def second_private_method
      # ...
    end

  protected

    def the_protected_method
      # ...
    end

end

Pros:

  • Visibility: easy to see if a method has a non-standard access modifier (non-public in most cases).
  • Produces a very readable code.
  • Used in the rails codebase (mainly older code).

Cons:

  • Semantically wrong: access modifiers do not create new scopes. They are simple method calls. Deeper explanation in the next item.
  • Methods inside the same scope with different indentation levels.
  • (opinion) One more level of indentation. When you have classes inside modules it starts being a problem: “indentation hell” :-). Your code ends up using its 80 columns very fast and you start having to break lines more often.

2. No indentation

Ruby access modifiers are simple method calls. The Module class (from which Ruby classes inherit) has the private, protected and public methods, that when called with no arguments, simply change the visibility of subsequent defined methods. You may confirm this by testing that the following code works:

class MyClass

  self.send(:private)

  def the_private_method
    # ...
  end

  def another_private_method
    # ...
  end

end

Try to call any of these methods in an instance of the MyClass class and you will confirm they are private.

Because access modifiers are simple method calls, they don’t create a new scope. Semantically speaking, they shouldn’t create another level of indentation. This is even advocated by one of the most important Ruby style guides.

class MyClass

  def the_public_method
    # ...
  end

  private

  def first_private_method
    # ...
  end

  def second_private_method
    # ...
  end

  protected

  def the_protected_method
    # ...
  end

end

Because of its correctness, this was my preferred style until recently, when I found the next ones.

Pros:

  • It is semantically correct: method calls don’t create new scopes, then method calls shouldn’t increase indentation levels.
  • (opinion) this style makes access modifiers look like python decorators, Java annotations and C# attributes. IMO, it’s one of the nice things about Ruby: its ability to reproduce most of other languages features, without requiring new syntax or fancy constructs. It’s a simple method call.

Cons:

  • Hard to see if a method has any non-standard access modifier. In classes with many methods (code smell!) you must constantly scroll to see what access modifier is applied.
  • Some would argue that this could be solved with proper syntax highlighting or visual method decoration. But it requires editor/IDE support, then I’m considering it as a disadvantage.

3. if-else style

We have a similar case in Ruby: the if keyword creates a new block and has associated else and elsif statements, which are also new blocks. The convention suggests the following indentation (note that if, elsif and else are in the same indentation level):

if something?
  2.times { play }
  jump(2.meters)
elsif other?
  sing and dance
else
  cry
  walk
end

Some of the code recently pushed to Rails 3.0 use the same indentation style for classes with access modifiers. I liked it:

class MyClass

  def the_public_method
    # ...
  end

private

  def first_private_method
    # ...
  end

  def second_private_method
    # ...
  end

protected

  def the_protected_method
    # ...
  end

end

Pros:

  • Easy to see access modifiers inside classes. With a fast look it is easy to identify sections of private, public and protected methods. They look like blocks.
  • Readable code. Similar to other Ruby constructs.
  • Used in the rails codebase (mainly newer code).

Cons:

  • Still semantically wrong. Access modifiers are inside the scope created by the class keyword. They should be indented.
  • if, elsif and else are keywords and have special meaning. Access modifiers aren’t and should follow the same convention of other method calls.

4. Indentation with one space

C++ also splits private, protected and public methods in sections. The construct is very similar to Ruby:

class MyClass {
 public:
  MyClass();
  void ThePublicMethod(int n);
  void Print(ostream &output) const;

 private:
  int *Items;
  bool FirstPrivateMethod();
  int SecondPrivateMethod();
};

While reading Google’s style guide for C++ code, their recommendation for public, private and protected sections indentation caught my attention. They suggest that you indent the private, protected and public keywords with only one space.

It seemed a bit awkward in the beginning. But soon, I started liking it because it makes sections easy to identify, access modifiers remain indented inside classes and methods stay all in the same indentation level, as they are all in the same scope.

class MyClass

  def the_public_method
    # ...
  end

 private

  def first_private_method
    # ...
  end

  def second_private_method
    # ...
  end

 protected

  def the_protected_method
    # ...
  end

end

Pros:

  • Easy to see access modifiers and sections inside classes.
  • Semantically correct.
  • All methods remain in the same indentation level.
  • Google style guide.

Cons:

  • People are always fighting for 2 spaces vs 4 spaces vs tabs indentation. One space? Very uncommon.
  • Special treatment for regular method calls. Statements inside the same scope with different indentation levels

My choice

Currently, I tend to like the 3rd (new Rails style) and 4th (Google) styles more. I somehow feel they give the best deal, considering their advantages and disadvantages. Being able to easily identify sections and access modifiers inside classes is very important to me.

In my current project, the team adopted the Google style. I’m happy with it, but you must be flexible in the beginning to adopt one-space-indentation. I won’t lie, it feels strange until you get used. Another issue I have is that my TextMate indent Ruby code with two spaces and treat them as one “step” when navigating with keyboard cursors. Then, I have to type a few more keystrokes to indent access modifiers the way I want. It’s hard to explain, you will have to try it yourself.

And you, what’s your opinion?
How do you indent access modifiers and their sections inside classes?