Friday, October 11, 2013

Can the 'new' keyword be harmful?

    I've heard somewhere that nowadays the object creation in Java is cheap. Every Java Developer knows the 'new' keyword and its purpose. However, does every Java Developer think about the consequences that are related to that keyword?
I'm not going to write about performance considerations or different ways of object creation. What I'm going to achieve is to present the importance of the proper 'new' keyword usage and its influence on code testability. Let's start with the following example:
public class Clothes {
    public void putOn(){}
}
public class Human {

    private Clothes clothes;

    public void goOutside(){
        clothes = new Clothes();
        clothes.putOn();
    }
}
Is there something wrong with that code?
With presented approach we are not able to obtain a full isolation of tested object. The 'new' keyword provides a very tight coupling and rigid connection between two objects. What is more, the 'new' keyword is used in the worst possible place - within a method (well, the newly created object can be replaced with a mock by means of PowerMock, however it should be considered 'last resort'). How can we solve that? What about:
public class Human {
    private Clothes clothes = new Clothes();

    public void goOutside(){
        clothes.putOn();
    }
}
We can write a pure unit test now:
@RunWith(MockitoJUnitRunner.class)
public class HumanTest {
    @InjectMocks
    private Human human;    
    @Mock
    private Clothes clothes;

    @Test
    public void shouldTestHuman(){
        human.goOutside();
        Mockito.verify(clothes).putOn();
    }
}
This is better, but still not ideal. Are we going to wear the same clothes all year long? The purest solution is:
public class Human {
    private Clothes clothes;
    public Human(Clothes clothes){
        this.clothes = clothes;
    }

    public void goOutside(){
        clothes.putOn();
    }
}
It is nothing new but our old friend - Dependency Injection (DI). We do not need any fancy framework (e.g. Spring, Guice) to perform DI. This simple example presents a constructor injection.
To sum up it can be said that objects in OO programming are as necessary as the air for breathing. However, that air can sometimes be toxic and if we realize that fact too late it can be lethal.

No comments :

Post a Comment