On a quest for the silver bullet..

Tell, don’t ask

Tell, don’t ask is a way of thinking when you’re programming software, a mindset. It is something that should be in the back of your head every time you write a line of code, or a chunk of code that describes some functionality. It is not something you merely apply when trying to solve a particular problem, it is something you apply all the time.

It is about how your entities communicate, it is about where you place your logic. It is about where to place the code. And when you are programming you are putting code somewhere all the time. That means this is one of the fundamental things to learn as a developer.

So, what is it?

The phrasing itself means that you should tell other objects to do things, instead of asking other objects for information and processing it yourself. (”you” are of course an object in this case).

Example: The car dealer

Say you’re making software for a car dealer. You want to create a report that lists all cars for sale that can be distributed to the customers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ForSaleReport
{
    private readonly List<Car> allCars;
 
    public ForSaleReport(List<Car> allCars)
    {
        this.allCars = allCars;
    }
 
    public List<Car> GetAllCarsForSale()
    {
        return allCars.FindAll(car => car.SoldDate != DateTime.MinValue);
    }
}

There is a violation of “Tell, don’t ask” right there:

1
car.SoldDate != DateTime.MinValue

You ask for information (the cars SoldDate), then make a calculation based on it (calculating if the car is for sale). So, what should you have done? You should tell the Car-object to resolve if it is for sale. It is not your concern to figure it out (when you are in the ForSaleReport), your only concern is to list out cars that are for sale, not why or how they are. So, instead of trying to figure things out yourself, you should just ask the car:

1
car.IsForSale()

Head in the sand Be ignorant

It is easier to apply Tell, don’t ask if you think of your objects as ignorant. You give them a responsibility, and beyond that they should be totally ignorant. Always ask someone else to solve the problems. This makes them ask less questions. Asking less questions means less coupling. Only caring for a single concern means higher cohesion.

And if I don’t .. ?

Didn’t you see the major difference between the two (asking for the SoldDate versus telling the car to figure out if it IsForSale)? Well, there is a difference, and normally it doesn’t take long before it shows.

Say you ask for the SoldDate (thinking Tell, don’t ask are for stupid programmers that wouldn’t understand as advanced logic as yourself..). And say that since this application is growing big you ask for SoldDate several places to resolve if the car is for sale (I’ve seen systems where asking for such “innocent” information is done hundreds of places). Then one day the owner of the car dealership comes to you, quite agitated, telling you that your reports are plain wrong: “A car doesn’t have to be for sale even though the sales date is not set. It can be held of or be in for repair. Fix it now!”

Hm, now you have to search for all the places where you did your “innocent” information asking, changing it everywhere, and test it to see if you broke something else. Pray that you do not have any indirect references to SoldDate (getting it from a car and sending it away for processing further away), that would be hell to track down. Wouldn’t it be better if you just had to change the logic in one place? in Cars “IsForSale” method? I would think so.

And that is not the only problem. Opening up a class, exposing information (like SoldDate in this case) makes it easier for other classes to hard wire itself to the class. This means more coupling, and more coupling means that the class will be harder to change. In this case, there is no way you easily can change the representation of SoldDate within Car. If you want to change it, you have to change every class that refers to it. This might be a very tedious task.

Another problem, which might not be so obvious since there is no “principle” attached to it, is the developer experience: How easy it is to write code in this system. I find this an important issue, and a bit underestimated at times. This is important because it has to do with productivity. When writing new code for this system, and you have to find out if the car is sold or not, it would be much easier just to write “car.IsSold()”, then it would be to actually have to find out how to calculate it, and then implement it (find somewhere else in the code that calculates it, copying that code, and so on…). Figuring out if a car is sold or not should be done once. When it is figured out and implemented, everyone else should just reuse that logic, never again caring for how it is implemented (unless of course, you have to fix or change something in that logic).

Conclusion

For me, Tell, don’t ask brings with it several realizations about programming:

  • It is important to think about your modelling when you write code. Where you put your code has major implications on your softwares maintainability.
  • Modelling isn’t just for “architects”. As a developer you make decisions every day that can make or break the software.
  • Focus on responsibilities, and who should be concerned with what. This makes your application more cohesive and less coupled.
  • Don’t repeat yourself (DRY). Tell, don’t ask helps you put logic one place (where its concern is handled) instead of scattering and copying it all around.
  • When modelling, it is also important to consider how easy it is to read and use the code for the developers.

So, if there is only one thing you want to keep in the back of your head when programming, I suggest it is Tell, don’t ask.

- Tore Vestues

August 16th, 2009 at 19:43 (863)


2 Responses to “Tell, don’t ask”

  1. Tore Vestues blogs » Law of Demeter: A real-world example Says:

    [...] exposing things through properties or getters), focusing on knowing as little as possible, applying “Tell, don’t ask”, and so [...]

  2. Nicki Ghelfi Says:

    Hi, i think that i saw you visited my web site thus i came to “return the favor”.I’m attempting to find things to improve my web site!I suppose its ok to use a few of your ideas!!

Leave a Reply