Ruby code style

Better Ruby: choosing convention for class methods definition

| 11 Comments

Ruby doesn’t have procedural module akin to Python or Perl module. Usually, one uses class methods as a typical way to mimic this functionality.

Class methods in Ruby are also very handy for supporting instance methods with fabrics and other common-for-class functionality. This is clearly seen in ActiveRecord::Base with dozens of supportive class methods (e.g. #find, #create, #where).

There are two standard approaches for defining class method in Ruby. The first one is the “def self.method” (let’s call it Style #1), and the second one is the “class << self” (let’s call it Style #2). Both of them have pros and cons. So, let’s take a look at them and try to decide which style is better and why.

Code sample

Here is “def self.method” style:

And the same example for “class << self” style:

Pros of “def self.method” style

1. It’s shorter and easier to add one method

It’s obvious, that Style #1 is two lines shorter due to the “class << self; end” part. This difference is noticeable for one/two methods. Also, it’s easier to add first class method because you don’t have to type “class << self” wrapper.

2. More simple for newbies

Usually Style #2 looks more exotic than Style #1; and, at first, the “class << self” part looks a little bit awkward.

Pros of “class << self” style

1. Class and instance methods are separated

Glancing over class definition, in Style #1 it’s hard to say, whether it’s a class or instance method. You need to focus on name part. On the other side, in Style #2 indentation and “class << self” wrapper clearly says who is who.

Another benefit of Style #2 – it’s easy to see amount of class and instance methods. They are not intermixed. Without clear separation it’s harder to work with class – you need to go over mix of methods and look for the required method.

Of course, you can take convention, for grouping class methods in one place, but it’s another rule, which should be followed by all, and it’s so easy to violate it occasionally. With Style #2 is much harder to accidentally create another “class << self” scope.

2. Easier to add batch of methods

What I especially appreciate in Style #2 – it’s easiness of adding new class methods. While Writing a new method, you shouldn’t be focused on adding “self.”-part in name. Class and instance method definition have the same syntax.

When I started my way in Ruby, it frustrated me a lot when I added class method and it didn’t work. And only then I realised that I actually forgot to add “self.”-prefix.

I strongly believe that a programmer should focus more on what he does and less on various language quirks. And after I switched to Style #2, these kinds of errors just disappeared from everyday coding.

3. Simpler search of method definition

“grep”-ing for some method is simpler to always search by “def name” combination. Style #1 also requires search by “def self.name”. This item is not a showstopper, but I run into this issue from time to time while searching through a code of different gems.

4. Simpler refactoring

What is started as object-oriented class can turn out to be a procedural module with a bunch of functions. To refactor instance methods into class methods you just need to add “class << self” wrapper and adjust indentation, which can be easily done in any editor.

On the other side, Style #1 requires to put “self.”-prefix in every method, which is tedious and can’t be archived with usual means.

Also, there is a case when you go into the opposite direction. Thing, which started as procedural module use some common context and should be refactored into class with instance methods. And again Style #1 requires removing of “self.”-prefix from all names, when in Style #2 you just remove “class << self / end” wrapper and adjust indentation.

Conclusion

It’s clearly seen, that “class << self” style has much more benefits than more commonly used “def self.method”. For me, the most crucial part is clear separation between class and instance stuff – because it improves code readability. I also like that Style #2 removes one class of errors from my Ruby programming.

Generally, we stick to the rules below while using it:

  1. Create “class << self” wrapper even for one method
  2. Put class-methods part at the top of the class

Following these rules will allow you to always find class-methods in a predictable place and in a predictable style.

Share
* Railsware is a premium software development consulting company, focused on delivering great web and mobile applications. Learn more about us.
  • Anonymous

    with class << self it is also possible to use the private keyword to create private class methods.

    • Wes

      With def self.foo syntax, you can make it private via private_class_method :foo. Not much difference there.

      • Sergii Boiko

        Indeed, big difference. It’s ugly to write such construction.

        I didn’t know, that “def self.method” isn’t put into private scope in case it’s follow private keyword. Now it’s even more preferable.

  • http://very-geek.com/ Albert Yu

    It’s good, now I know another way to define class methods, thanks.

    By the way, can you explain me a little about awkward “class << self"? What's going on behind the scene? How does it work to transfer regular method definition to class-level?

    Or some references on this topic will appreciated.

  • Anonymous

    For the case where you’re looking to implement just a package of related functions, you probably want a Module over a Class (the biggest difference is that you can have instances of a Class). The approaches you’ve outlined here work fine for Modules as well, but you also get a third option: extend self.

    module Foo
    extend self # “extend” means “add this module’s methods to me”

    def bar(n)
    double(n) * 5
    end

    def double(n)
    n * 2
    end
    end

    Foo.bar(3) # => 30

    # As a bonus, you can also include modules in other modules and classes!
    class SomethingImportant
    include Foo # “include” means “add this module’s methods to instances of me”

    attr_reader :value
    def initialize(n)
    @value = bar(n)
    end
    end

    SomethingImportant.new(6).value # => 60

  • Marius Pop

    If you have a class with many instance methods and class level methods and you use class << self a new programmer can end up confused upon the true nature of the method. (You may end up at one point with so many methods that you don't see the class << self line) self.method_name is much more explicit. I would only use class << self if I have no instance methods in my class.

    • Sergii Boiko

      In my experience, never run into this issue. Anyway, right now, after first comment, “class << self" method even more preferable, because "def self.method" require clutches to define private methods.

  • V

    Check head version of Ruby syntax ;)

    • Sergii Boiko

      Can you provide some link? =)

Want to get more of Railsware blog?

RSS FEED

We're always ready to help!

CONTACT US