success_logo

Your form has successfully submitted

One of our teammates will get back to you soon.

Null Object Pattern

Null Object pattern can reduce you some code complexity and it's pretty simple to use.


A design is far better when there are no exceptions. Whenever you write an if statement, Nyan Cat cries.

Yesterday I remembered this blog quote when I faced a common situation handling nested hashes in Ruby.

hash = {
  company_name: "Stack Builders",
  address: {
    line_1: "315 Fifth Avenue",
    line_2: "Suite 703A",
    city: "New York",
    state: "NY",
  },
}

What if I want to get some of that data and use it to manually instantiate a Company entity? Wll, attributes for that entity are not nested like the hash is:

Company.new(
  name: hash.fetch(:company_name),
  address_line_1: hash.fetch(:address).fetch(:line_1),
  address_line_2: hash.fetch(:address).fetch(:line_2),
  city: hash.fetch(:address).fetch(:city),
  state: hash.fetch(:address).fetch(:state)
)

That's not the most beautiful piece of code, but it works if--and only--if all keys are present. If not fetch will complain. You can say, "But what if we use [] method instead of fetch?" Well, if the address key is missing in our hash, the code hash[:address][:line_1] will throw a NoMethodError for NilClass. Not ideal.

What now? "Add an if, it will fix that." Mmmm... yes, it will solve the problem, but do you remember the quote at the beginning of this post? I want to avoid adding if statements to this piece of code. This is where the Null Object pattern enters.

I used a very simple implementation of this pattern just to satisfy cases like this one. We can use it in many different ways and have a lot of flexibility, I just wanted to avoid the NoMethodError being thrown again.

# null_object.rb
class NullObject
  def method_missing(*args, &block)
    nil
  end
end


# company.rb
address = hash.fetch(:address, NullObject.new)
Company.new(
  name: hash.fetch(:company_name),
  address_line_1: address.fetch(:line_1),
  address_line_2: address.fetch(:line_2),
  city: address.fetch(:city),
  state: address.fetch(:state)
)

This way the NullObject instance is just nullifying my call to fetch, because I don't have that :address key. This improved my design, simplified my code, and made it safer.

Why don't you go ahead give it a try? It might be as helpful for you as it was for me. Here I created my own implementation of this pattern, a very simple one, no fanciness needed, but if you want something more sophisticated check out Naughy, by Avdi Grimm.

Published on: Nov. 21, 2014

Written by:


Software Developer

Filipe Costa