Tell Don't Ask Design Principle

Overview

This article describes the design principle called Tell, Don't Ask. This principle is intended for designing classes in such a way that when they are used, instead of querying their object/instance and performing the operation based on the output it provides, the instance should handle the logic itself.

In other words, it means, the instance of the class should make the decision itself, rather then calling the code telling it what to do. So let's discuss with a code sample what violates the principle and then we will implement it using this principle.

Consider the following piece of code. Here, we have the following business logic implemented.

 
 


We check for the discount applicable on the vehicle. If it is greater than 5%, we subtract 5000 from the actual price else 3000, as a discount. We also have a net price price defined for the vehicle. After applying the discount, if the net price is more than this base price, we can further provide free accessories else we do not.

This type of code will have the following issues:

  1. If we have the same type of logic in other areas of the application then changes in the logic will require changes in all the locations.
     
  2. The client code is now aware of the business logic to calculate the cost of the vehicle.
     
  3. Some of the member functions/properties are unnecessarily exposed as public members to the client code.

This is where we can use the Tell, Don't Ask principle. So we change our code to shift the entire logic into the CostCalculator class and pass the required data to it. It calculates the net price and based on results, it decides whether or not it needs to make a further call to the ApplyAccessories() method. Our code now changes to:

New C Sharp Code

So in this case, the entire calculation logic, along with the logic to add accessories, is inside the CostCalculator class. We simply provide the required data as input to this class. Further, the ApplyAccessories method is now converted into a private method and the client code has no idea of the cost calculation business logic. The client code will simply pass the data to the CostCalculator and the rest will be done by its NetCalculation method. In other words, we are telling the CostCalculator instance to perform the calculations, rather than asking anything from it.