Tell, Don't Ask

Ben Orenstein

And now, a friendly message from your local Tell, don’t ask Department.

Example 1

Not so good:

<% if current_user.admin? %>
  <%= current_user.admin_welcome_message %>
<% else %>
  <%= current_user.user_welcome_message %>
<% end %>

Better:

<%= current_user.welcome_message %>

Example 2

Not so good:

def check_for_overheating(system_monitor)
  if system_monitor.temperature > 100
    system_monitor.sound_alarms
  end
end

Better:

system_monitor.check_for_overheating

class SystemMonitor
  def check_for_overheating
    if temperature > 100
      sound_alarms
    end
  end
end

Example 3

Not so good:

class Post
  def send_to_feed
    if user.is_a?(TwitterUser)
      user.send_to_feed(contents)
    end
  end
end

Better:

class Post
  def send_to_feed
    user.send_to_feed(contents)
  end
end

class TwitterUser
  def send_to_feed(contents)
    twitter_client.post_to_feed(contents)
  end
end

class EmailUser
  def send_to_feed(contents)
    # no-op.
  end
end

Example 4

Not so good:

def street_name(user)
  if user.address
    user.address.street_name
  else
    'No street name on file'
  end
end

Better:

def street_name(user)
  user.address.street_name
end

class User
  def address
    @address || NullAddress.new
  end
end

class NullAddress
  def street_name
    'No street name on file'
  end
end

Good OOP is about telling objects what you want done, not querying an object and acting on its behalf. Data and operations that depend on that data belong in the same object.

Tell, don’t ask!

Detect emerging problems in your codebase with Ruby Science. We’ll deliver solutions for fixing them, and demonstrate techniques for building a Ruby on Rails application that will be fun to work on for years to come.

Grab a free sample of Ruby Science today!