3 wise men on Tell Don't ask

A story on Tell Don't ask Principle

wisemen.jpg

John, Doe, and Marcus are three good friends. They have over 20 years of experience Java/JEE stack and working in IBM, Cognizant and TCS respectively. They have immense experience in design pattern and all the new technologies and respected by their colleague for Exceptional insight on the Technology Stack.
They are planning to go for a vacation in the upcoming weekend to enjoy their spare time with lots of Burger, whiskey, and cooking. John has an Outhouse in a village so they planned to go there by driving.
At last, the day came they pack their Beer, Whiskey, and Burger and headed towards John outhouse it was far away from Town. At evening they reached the outhouse and prepare some snacks for their whiskey and sit together in a round table to enjoy Chicken roast and Whiskey.
Suddenly the power cut happens, The room is so dark that no one can see anything, from outside they can hear the Call of Cricket, Marcus put on his mobile flashlight, now they can see each other.
Doe breaking the silence by saying,
“Oh well, this ambiance is perfect for a horror story can anyone share any real life experience?”
Marcus replied in a witty way
“Umm No, I believe all we are from town and busy with IT industry so sorry can not share any horror experience but can share some Java experience which still frightened me”
John and Doe’s Architect instinct flashed with this proposal.
They said, “ Oh yes what would be more good to discuss about something which frightened us an Architect in this ambiance, it is same as Horror Story :).”

Marcus slowly demonstrated the problem.
Marcus: As an Architect when I design a solution for a problem it always frightened me what we encapsulate and what portion we expose to our client program?
John and Doe Nodded their head.
Marcas Continue with his speech,
There are lots of OOPs principle which says how judiciously you can encapsulate your classes or API from outside world.
Take an Example, The  Tell Don’t Ask principle, It says us always tell to Object, in a layman term instruct Object what to do never query for an internal state and take a decision based on that because then you loose control over the object.
Take a simple example suppose I want to write a Parcel Delivery Service and there are two domain Objects Parcel and Customer so how should we design it.
If I write following code fragments

/**
*
*/
package com.example.basic;

/**
* @author Shamik Mitra
*
*/
public class PercelDeliveryService {
   
   
    public void deliverPercel(Long customerId){
       
        Customer cust = customerDao.findById(customerId);
        List<Percel> percelList = percelDao.findByCustomerId(customerId);
       
        for(Percel percel : percelList){
           
            System.out.println("Delivering percel to " + cust.getCustomerAddress());
            //do all the stuff for delivery
        }
       
    }

}


According to Tell Don’t Ask it is a violation and should be avoided. In Parcel Delivery Service I try to fetch or ask Customer Address so I can perform the delivery operation so here I query the internal state of the Customer.
And why it is dangerous?
If later if the delivery functionality change says now it also include an email address or mobile so I have to expose these details so exposing more and more internal state think about the other services they may also use the same email address or Customer address. Now If I want to change the Customer Address return type String to Address Object then I need to change all services where it has been used, so a gigantic task to perform and increases risk factor of breaking functionality. Another point is as internal state is exposed to many services there is always a risk to pollute the internal state by a service and it is hard to detect which service changed the state. In one word I loose the control over my object as I don’t know which services use/modify my Object internal state. Now if my object is used by the Internal services of a monolith application I can search the usage in IDE and refactor them but If the Object is exposed through an API and This API used by other organization then I am gone, It really hurts our company reputation and as an architect, I would be fired.
So I can say

Action: More you Expose Internal state
Outcome:  Increase coupling, Increases Risk, Increase Rigidity.


Now again look the solution I provided,
Doe chuckled and guess which point Marcus trying to make so he interrupted him and start saying.
Doe: So Marcus you want to tell if we follow Tell Don’t Ask principle then there are couple of ways we can refactor the problem
1. make an association between Customer and Parcel . and it would be lazy loaded and deliver method should be in Customer Object so from the service we call deliver then deliver method fetch parcel list and deliver it, so if the Internal return type change from String to Address only “deliver” method should be affected.
Like this,
/*
*
*/
package com.example.basic;

/**
* @author Shamik Mitra
*
*/
public class ParcelDeliveryService {
   
   
    public void deliverParcel(Long customerId){
       
        Customer cust = customerDao.findById(customerId);
        cust.deliver();
    }

}

public class Customer{

    public void deliver(){
        List<Percel> percelList = getPercelList();
      for(Percel percel : percelList){
           
            System.out.println("Delivering percel to " + this.getCustomerAddress());
            //do all the stuff for delivery
        }
       
    }
}



By doing this I maintain Tell Don’t Ask principle properly and decreases the risk of exposing internal state and free to modify my class attributes as all behaviors are tied locally with attributes a nice way to achieve encapsulation.
2. We can create a command Object where we pass the Parcel details and pass the command object to Customer Model, the delivery method extracts the Parcel list and deliver it to the respective customer.
But both policy breaks another principle that is Single Responsibility Principle, SRP(Single Responsibility Principle) says A class has only one reason to change.
But If I think in a reverse way, why we write Services? Because each service does one job like Person Delivery Service responsible for “delivery parcel related “ operations so it maintains SRP and this service only change if there are any changes in Parcel Delivery mechanism and if it breaks other services will not be affected unless other services depend on it.
But according to Tell Don’t Ask all Customer related behaviors should be moved into Customer class so we can tell /Instruct/command Customer class to do a task. So Now Customer class has much responsibility because all Customer-related service code now goes into Customer Model. So Customer has more reason to change so increase the risk factor of failing.
So Now we are back in the same problem risk factor.
If exposing internal state then the risk for modifying attribute if move all behavior into a class then the risk of modifying functionality break the system.
So SRP and Tell Don’t Ask principle contradict in this context.

John: John nodded his head and started with his husky voice, Yes this is really a problem
not only this, If we want to implement a cache in a service or want to implement Aggregation function like Percell delivery rate charge according to distance or Account type, Find most parcels sent to a locality we use Aggregator service where we ask for internal state and compute the result. So often we break Tell Don’t Ask principle. Even as per current trend, Model Object should be lightweight and should not be coupled with each other. If the business needs an information which distributes over multiple models we can write an aggregator service and query each model and compute the result , so we querying internal state. Think about Spring data.
Now If we look in another perspective, according to the Domain-driven Design, In a Parcel Delivery Context (Bounded context) is Customer responsible for delivering the parcel?
Absolutely not, In that context Delivery Boy is responsible for delivering the parcel to the customer. For that Delivery boy needs Parcel and Customer Model, and in that context only Customer name and Address details required and for parcel Id, parcel name will be required so as per DDD we create an Aggregate Model DeliveryBoy where we have two slick Model Customer and Percell because in this context we don’t need customer other details and parcel other details like customer account details, Customer birthdate etc, Context wise model is changed so no one big model for customer where all attribute and behaviour resides rather small slick models based on bounded context and an Aggregate model querying these slick model and perform the work.
By doing this we can mix and match SRP and Tell Don’t ask. For a service perspective we only tell /command DeliveryBoy Aggregate model to do something, so Service maintains SRP and Tell don’t ask, Our Aggregate model also maintain SRP but querying Customer and Parcel Model to do the operation.

Like



/**
*
*/
package com.example.basic;

/**
* @author Shamik Mitra
*
*/
public class ParcelDeliveryService {
   
   
    public void deliverParcel(Long customerId){
       
        DeliveryBoy boy = new DeliveryBoy();
        boy.deliver(customerId);
    }

}

public class DeliveryBoy{
    Customer cust;// Context driven model
    Percel percel;
    public void deliver(Long id){
        //do stuff
//load customer slick model
//load Percel slick model
//Deliver the same by quering

        }
       
    }
}

Marcus joined and says let's take one step further as DDD insists  Microservice, so in Microservice we try to break a monolith using functional decomposition( A function is a Bounded context in DDD) so one service doing one task maintains SRP principle and if we needed and information which distributes over multiple services we create an Aggregator service and querying individual service and do the task so Microservice often breaks Tell Don’t Ask
Doe joined and says So there is no silver bullet and not all principles are good in all context, Based on the context you have to judge which principles you follow sometimes you need to compromise, may for a specific principle viewpoint your code is bad but for a given context it is optimum.

Principles are generic and they are context free but real life solution are based on context so fit principles based on context not the reverse.

In the meantime Light comes, so John said here we are for fun let stop the discussion and concentrate on Whiskey and Roast !!!!
Everyone agreed and change the topic.
Conclusion : As a Narrator, My question to all viewers, what do you think about the talk they did, is there are any points they left off which needs attention while designing?

Why should I write Getter/Setter?

Why should I write Getter/Setter?

When I started my career in Java, I was confused about getter and setter. One question always comes to my mind why should I write getter/setter? It looks weird kind of syntax to me.

I learned that by public access modifier one field of a class is accessible to any packages, and by Getter/setter what I am doing is same, make the field private and public the getter/setter method, so it can be accessed by any packages.

So, What is the difference between following two expressions?


public String name=”Shamik”;

Caller
========

String name = X.name;   //(X is a object instance);
X.name=”Shamik Mitra”;
private String name=”Shamik”;

public String getName(){
return name;}

public void setName(String name){
this.name=name;}

Caller
=====
String name = X.getname();
X.setName(“Shamik Mitra”);


confused.jpg
What the heck is getter/setter?




Slowly I realize why we use getter/setter & why it is important.

In this Article, I share that realization.

Realization :

The main difference of making a field public VS expose it through getter/setter is to hold the control to the property.If you make a field  public that means you provide direct access to the caller, caller can do anything with your filed knowingly/unknowingly say, caller can send a null value and if you use that filed in another method it may blow up that method by null pointer exception,

But If you provide getter/setter, you provide them an indirect access while taking full control, because the only way to set a value through setter and get a value through getter, So now you have exact one entry and one exit point of your field and getter/setters are methods!!! (Which allows block of codes) so you can do validation check on them and takes the decision you should set the caller value or not, same in getter method you can take decision should you return the actual reference or clone it and return the same to the caller.


So, getter/Setter are work as fuse or circuit breaker where the current has to be passed through fuse if anything goes abnormal fuse detached from the main circuit, so the circuit is safe. The concept is same here if anything goes wrong setter will not pass the value to class member field.

After reading the explanation, I know still you have one question

I understand all but generally, we do not write anything in getter/setter just return the field and set the field, which is same as exposing a field as public so why are you saying all of this?

To answer this question I say writing getter/setter we create a provision to add any validation method in future, currently, there is no validation but if anything goes wrong in future we just add validation logic in the setter.

But still, it creates a debate who are big follower of YAGNI(You aren't gonna need it),
they can say when there are no such validation constraints for a field why should I write getter/setter, I only expose it as public.

As per my understanding, The crux of YAGNI is to Unnecessary not make your code complex, As someone like to think big and try to make their code base so generic that it welcome any changes but most of the changes he/she thinks will never come.

Conclusion: The  getter/setter does not make your code complex and welcome future validations. So Please go for it blindly.




5 Curious cases of Overloading & Generics

5 Curious cases of Overloading & Generics


If you are preparing for an Interview you can expect questions on  generics in java interview for sure , whether it is an position for Team lead or experience developer or Junior. But Generics gets more complicated when it mix with overloading in java. Let see the different scenarios when Generic mix with overloading.

What is generics in Java ?

Generics is technique which facilitates to declare a generic type(T, Irrespective of any Datatype in Java) in methods or class, which will be resolved later when caller of the method or class provide the actual Data Type(Integer, Boolean, String or ant Custom class) and ensure compile time safety but at the run-time it removes the type safety, we call this process as Type erasure.

Benefits of Generics:

By generics, we can achieve some level of the generic type declaration. To be specific Java is a static type language which means when we declare properties or methods we have to provide the type of the parameter or return type at the time of declaration.

But by generics we can defer the process we can declare methods or properties using generic syntax and later on caller can decide what data type pass to it, but remember it is not same as dynamic type language like javascript where var declaration means it represents any data types, on other hand Generics introduce the Type Inference from a bounded context, from Java perspective which is the first step towards functional programming(lambda) adaptation.

Challenges :

The most tricky part of generics is  by Type erasure, java removes the bounded type at runtime, so in java runtime generics and non-generics method/property declaration both are same no difference at all, to maintain backward compatibility  but generics ensure compile time safety so if you declare generics with certain type it only bounds to that certain type if you want to pass any other type compiler will complain instantly.

But as run time its type vanishes so in the case of Overloading we have to think what the method looks after type erasure erases the generic type, to do a perfect overloading unless compiler will complain.

In this Article, we will see 5 such scenarios which can occur often if I miss any please write in the comment section so I can add them to the Article.


Hope you are familiar with the generic syntax and how to use it.




Scenario 1 :

public Integer add(Integer a, Integer b) {
        System.out.println(a+b);
        return a+b;
    }

    /* (non-Javadoc)
    * @see com.example.generics.ICalculate#add(java.lang.Object, java.lang.Object)
    */

    public <T> T add(T a, T b) {
       
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return (T) resut;
       
       
    }


See the two versions of add method can you tell me is it a valid overloading?

Yes this is a valid over loading as after type erasing public <T> T add(T a, T b) this method signature converts to , public Object  add(Object a, Object b) clearly it is different than
public Integer add(Integer a, Integer b) .



Scenario 2:

Now see the following version of overloading


public <T> T add(T a, T b) {
       
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return (T) resut;
       
       
    }
   
   
   
public  Object add(Object a,Object b) {
       
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return  resut;
       
       
    }



Can you tell me is it a valid overloading?

Probably you guess the answer it is not as I told you in previous example public <T> T add(T a, T b) this method signature converts to , public Object  add(Object a, Object b) after type erasing so now both signatures looks same so compiler will complain.


Scenario 3:

Now take the following version

public <T> T add(T a, T b) {
       
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return (T) resut;
       
       
    }

public <T extends Number> T add(T a, T b) {
       
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return (T) resut;
       
       
    }


Is the above a valid Overloading?

Yes it is a valid overloading as after type erasing  public <T> T add(T a, T b)  changed to public Object add(Object a,Object b) but public <T extends Number> T add(T a, T b)  changed to
public Number add(Number a, Number b) as T extends Number means any type which extends Number so after Type erasing it will take Number as infer type.


Exercise :

Can you tell me Is it valid overloading with explanation -- without paste that code in editor?
public Integer add(Integer a, Integer b) {
        System.out.println(a+b);
        return a+b;
    }


public <T extends Number> T add(T a, T b) {
       
    System.out.println(a.getClass().getName());
        Integer a1 = (Integer)a;
        Integer b1 = (Integer)b;
        Integer resut = a1+b1;
        System.out.println(" Result is" + resut);
        return (T) resut;
       
       
    }



Now let take a slightly different example where I try to pass a data type to a collection which will be the bounded context for that collection.

Scenario 4:

public void add(List<Integer> list) {
   
    System.out.println("add list of Integers");
   
   
}

public void add(List<?> list) {
   
    System.out.println("add/concat  list of any type");
   
   
}


Is it a valid overloading?

The Answer is, unfortunately, no, because after type erasing generics will lose its type and would become same as our old list.

So both signatures public void add(List<Integer> list)  and public void add(List<?> list) change to  public void add(List list)  and public void add(List list) so compiler will complain for sure.


Scenario 5 :


public void add(List<Integer> list) {
   
    System.out.println("add list of Integers");
   
   
}

public void add(List<Double> list) {
   
    System.out.println("add list of Integers");
   
   
}


As previous reason it is also not a perfect overloading.

So always pay attention of your generics signature while extending a class or overload method.