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?

Advertisement

Rfactor: Ruby Refactoring for your loved editor

I know we all love Ruby, and doesn’t care that much about not having auto completion/IntelliSense available.

I don’t care that much about auto completion, when coding in Ruby, myself. What I really like in Java IDEs is their refactoring support. Eclipse and IntelliJ IDEA are simply awesome in this space for Java. We still have ReSharper for Visual Studio and others, targeting other languages. Ruby has NetBeans, Aptana RadRails, RubyMine and TurboRuby/3rdRail doing a great job in this area.

But, I have this feeling that most of Ruby developers do not use IDEs (including myself). We are using good text editors, such as TextMate, Vim, Emacs and GEdit. They are good enough. Why would I need something else?

I have to admit. I really miss some refactorings while programming in Ruby. Particularly, the lack of “Extract Method” and “Extract Variable” bothers me. They aren’t even complicated, why hasn’t someone already implemented them?

So, I would like to introduce Rfactor. It is a Ruby gem, which aims to provide common and simple refactorings for Ruby code. RubyParser from Ryan Davis is being used to analyze and manipulate the source code AST, in the form of Sexps.

In theory, we should be able to use Rfactor to power any editor, adding refactoring capabilities to it. I’m targeting TextMate, but I would love to see contributions for others. The TextMate Bundle is hosted on github:

Rfactor TextMate Bundle, with installation instructions

This very first release has support only for basic “Extract Method”: inside methods and without trying to guess the method parameters and return.

Stay in touch, there is much more coming!