This blogpost was posted on Hacker News with several upvotes. Coming from C++, most of these examples seem to go against what I've been taught.

Such as example #2:

Bad:

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


versus good:

system_monitor.check_for_overheating

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


The advice in C++ is that you should prefer free functions instead of member functions as they increase encapsulation. Both of these are identical semantically, so why prefer the choice that has access to more state?

Example 4:

Bad:

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


versus good:

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


Why is it the responsibility of User to format an unrelated error string? What if I want to do something besides print 'No street name on file' if it has no street? What if the street is named the same thing?



Could someone enlighten me on the "Tell, Don't Ask" advantages and rationale? I am not looking for which is better, but instead trying to understand the author's viewpoint.

Asking the object about its state, and then calling methods on that object based on decisions made outside of the object, means that the object is now a leaky abstraction; some of its behavior is located outside of the object, and internal state is exposed (perhaps unnecessarily) to the outside world.


  You should endeavor to tell objects what you want them to do; do not
  ask them questions about their state, make a decision, and then tell
  them what to do.
  
  The problem is that, as the caller, you should not be making decisions
  based on the state of the called object that result in you then
  changing the state of the object. The logic you are implementing is
  probably the called object’s responsibility, not yours. For you to
  make decisions outside the object violates its encapsulation.
  
  Sure, you may say, that’s obvious. I’d never write code like that.
  Still, it’s very easy to get lulled into examining some referenced
  object and then calling different methods based on the results. But
  that may not be the best way to go about doing it. Tell the object
  what you want. Let it figure out how to do it. Think declaratively
  instead of procedurally!
  
  It is easier to stay out of this trap if you start by designing
  classes based on their responsibilities; you can then progress
  naturally to specifying commands that the class may execute, as
  opposed to queries that inform you as to the state of the object.


http://pragprog.com/articles/tell-dont-ask
