"Tell, don't ask" works on the premise that an object shouldn't have to be told to do something according to some information about the object itself. Surely the object should know its own state? You shouldn't have to couple code outside of the object to perform some function it could very well do itself. I found the example picture terribly confusing so I'll use another example instead.
Imagine you play a complex game such as World of Warcraft. You are a warlock and you want to use the Fear spell on some other player. The spell should send them running for 8 seconds. If you cast it again that time will be halved due to diminishing returns, and so on. There are many factors deciding if the spell hit should be a success or not.
Now, the Fear spell could be implemented like this:
function castFear(Player player) {
if (player->isAPaladinAndFearsNothing())
return false;
if (player->hasTakenAntiFearPotion())
return false;
if (currentPlayer->getStat("shadow_magic_power") < player->getStat("shadow_magic_resistance"))
return false;
player->receiveFear();
}
With "tell, don't ask" this code could be simplified drastically:
function castFear(Player player) {
player->receiveFear(currentPlayer);
}
The Player class could be implemented like this:
class Player {
public boolean receiveFear(Player castingPlayer) {
if (this->isAPaladinAndFearsNothing())
return false;
if (this->hasTakenAntiFearPotion())
return false;
if (castingPlayer->getStat("shadow_magic_power") < this->getStat("shadow_magic_resistance"))
return false;
// Get feared
}
}
Now, both solutions might seem quite similar, but if you think about it, whose responsibility is it to know if the target player can be feared or not? "Tell, don't ask" might appear as a "neat trick", but I've found this style of coding to be one of the cornerstones of OOP. You should not know of whatever complexity is hidden behind that public function and as such should not take action against it either. What if some of your new spells should also Fear your target? You'd have to stay up to date on all the checks you'd have to make, everywhere. If you wanted to implement "Healing Horror" that fears your target and heals you, you could just write:
function castHealingHorror(Player player) {
currentPlayer->health += 50;
player->receiveFear(currentPlayer);
}
I'd say this is also a question of which object should perform the checks, the sender or the receiver? Well, think about it. If you were to send a letter to an official containing inappropriate wording, wouldn't your letter be halted somewhere along the way? For all you know someone might read the mail before your recipient does and filter it out as a security measure. Should you code for this as the sender? All you should do is take your prepared Letter
object, give it to the mailman and that's it. Maybe it doesn't even reach the destination post office due to some inconvenience.
Expose yourself to as little complexity and information as possible and let each component deal with its own business rules. It's then easier to combine them into a fully encapsulated system.