Use static facades when you don’t care about the instance

Using class methods to drive the behavior of your class.

When writing Ruby, instead of this:

Table::Load.new(file).perform

I believe you should do this instead:

Table::Load.perform(file)

Why?

It reduces coupling and simplifies maintenance

Both the constructor and the “perform” method are part of the public API of Table::Load By reducing the public API you reduce coupling and reasons why callers may have to change.

It simplifies unit-testing

When unit testing, you don’t want the code under test to execute the code inside Table::Load. By making just one method call, just one simple stub/expectation is needed:

expect(Table::Load).to receive(:perform)

Instead of

load = double
allow(Table::Load).to receive(:new).and_return(load)
expect(load).to receive(:perform)

It allows complexity to be introduced without changing every caller

This is related to the first reason. Lets say you need to create different types of classes depending on a characteristic of the file to be loaded. Instead of having to leak that problem into the caller, you can hide that change inside the static facade. The caller doesn’t care about which implementation is being used to load the file — it just want it to be loaded. This allows you to introduce complexity inside Load::Table while keeping the usage simple. One example could be

class Table::Load
  def self.perform(file)
    if file.end_with?(".gz")
      new(GzFile.new(file)).perform
    else
      new(PlainFile.new(file)).perform
    end
  end
  # constructor and perform here...
end

This can be later extracted to a builder or factory if necessary.

But class methods are a mess!

I agree. Class methods resist refactoring due to lack of instance state and even suffer from visibility inconsistency.

That’s why the underlying implementation should be the same:

class Table::Load
  def self.perform(file)
    new(file).perform
  end
  # constructor and perform here...
end

Another reason why I prefer to encapsulate those two calls is because the class method makes the usage of this class explicit. I believe that anyone who sees that class will immediately learn how the class is intend to be used.

I also think this kind of construction is resistant to the introduction of many other public methods. If you feel you need that, you probably want to introduce/extract a new class.

The only drawback of this design is the extra class method, but I find that acceptable given the benefits. One option to mitigate this small issue is using a gem like attr_extras. With it, the final code would be:

class Table::Load
  static_facade :perform, :file
  # constructor and perform here...
end

Here is the documentation for the static_facade.

The next step

You can even go one step further by naming your class as an action and rename your static facade to “call” or whatever is the convention on your language for callable objects. Those are sometimes called method objects. The attr_extras gem for Ruby also has a macro for that named method_object.

Method objects like that work better when they represent “outer layers” of your system or a complicated but well defined process.

What do you think? Do you see the benefits of this approach? Can you think of drawbacks of this kind of design?

Show Comments