In
this article, we will be discus about a design principle called Tell, Don't Ask. This principle is aimed at
designing the 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 take the decision
itself, rather then calling code telling it what to do. So let's discuss
with a code sample which violates the principle and than will implement the
same 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 net price is more than this base price, we can
further provide free accessories else we do not.
This
type of code will have following issues:
1.
If we have same type of logic in other areas of application, changes in
the logic will require changes in all the locations.
2. 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.
2. 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 it further needs to make a call to the ApplyAccessories()
method or not. Our code now
changes to:
So
in this case, the entire calculation logic, along with logic to add
accessories, 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 client code has no
idea of the cost calculation business logic. Client code will simply pass the
data to the CostCalculator
and 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.