Compilation Failure is the best Failure!

What I am going to write may sound really obvious but surprisingly I see this problem at soo many places that it deserves a post.

Here's a Rule 1: "If you are doing an instanceof and you are in control of that class, you can instead delegate to the class"

Meaning, if you were making a decision of what code to execute by checking an instanceof and the class being checked is the one that you control, as in the one that you can modify, add methods change code, then you should delegate the decision of what should be executed to that class instead.

Lets look at an example,


public static void speak(Animal animal) 
    if (animal instanceof Dog) {
         System.out.println("bhow.. bhow...");
    } else if (animal instanceof Cat) {
         System.out.println("meow.. meow...");

    } else if (animal instanceof Tiger) {
         System.out.println("Grrrr...");
    }
}

could really be changed to,

Animal animal = getAnimal();
animal.speak();

Where classes Dog, Cat and Tiger now will implement the speak() method.

It sounds really obvious doesn't it? If it really does, just do a search of instanceof keyword in your code and ask the same question. The "speak" operation comes very naturally to the Animal but sometimes you will find that since we don't think something is natural to that Entity or class, we don't add it there.

There is an anti-pattern called "Anemic Domain Model" which will specially suffer this problem. This pattern encourages to keep the Behavior separate from the Data. Which is what is happening in above example. One very simple way to find it is to see how many classes are named "Entity" and "EntityService"? If the EntityService operates on a single instance of the Entity like single animal, then  you have a problem. Don't confuse this with the one's that operate on multiple instances like a "EntityManager" or an "EntityDAO"

So what is really wrong with writing an if else-if  and checking instanceof to make decisions? Lets consider that in above example, we added another Animal Cow. Now what can happen is that in our first version of "speak" one can forget to go and add code for a Cow. This is perfectly fine, code compiles! We have implemented the Animal interface but there are no complains. This would only lead to either runtime failure or no failure at all! which ultimately leads to bugs. Think about a larger project where the references are at a lot of places. If the "speak" method is at the level of Animal interface, you have no choice but to implement this method (God help people who will still keep it empty)

Which brings me to my Rule 2: "Compilation Failure is the best failure!"