Grasping Dependency Injection in the context of two simple classes

Bolaji :

I have been having issues grasping Dependency Injection(or let me say its benefit). So I decided to write two simple pieces of code of one without DI and the other with it.

So I have a class A

public class A {
    public void foo(){
        B b = new B();
        b.fooB();
    }
}

as can be seen above A depends on B, B which is

public class B {
    public void fooB(){
        Log.e("s", "y");
    }
}

and we can use A like

public void do(){
    A a = new A();
    a.foo();
}

But it's said that A should not simply initialize B because it depends on it, however we should have have a service that have some sort of contracts between the two classes. For Example, please if I am wrong kindly let me know

So lets have an interface BService

public interface BService {
    void fooB();
}

And B becomes DiB

public class DiB implements BService {
    @Override
    public void fooB(){
        Log.e("s", "y");
    }
}

And A becomes DiA

public class DiA {
    BService bService;

    public DiA(BService bService){
        this.bService = bService;
    }

    public void foo(){
        bService.fooB();
    }
}

and we can use A like

public void dIdo(){
        BService service = new diB();
        diA a = new diA(service);
        a.foo();
}

So I read benefits of DI are :

  1. Testable codes : Because I can actually test both codes in JUnit(I dont want to post the test here to avoid long question)
  2. Decoupling: Its said that if class B changes then A shouldn't be affected, and I cant grasp that because If i change fooB() in class B to fooB2(), i will have to change the override method in BService which in turn means i will have to change it in class A

Both codes seems to work fine and I cant fathom benefit of one over the other, only that the other is more complex. So please can you enlighten me more on the benefits in the context of this simple A and B classes. What am I not getting?

Michael :

You don't need the interfaces you've created for it to be classified as dependency injection. This class is using dependency injection:

public class A {
    private final B b;

    public A(B b) {
        this.b = b;
    }

    public void foo(){
        b.fooB();
    }
}

Don't overthink it. 'Dependency injection' sounds like a complicated concept when you don't understand it but the name actually describes the concept perfectly and concisely. Let's break it down:

Dependency: Things that something relies upon
Injection: The act of putting something external inside something else

In the above example, are we putting the things we rely upon inside our class from the outside? Yes we are, so we're using dependency injection. Whether our class implements an interface or not is irrelevant.

There are good reasons why implementing classes to interfaces is a good idea but that is tangential to dependency injection. Don't get these things confused and don't think that it's a requirement.


Addressing testability: yes, in your non-dependency injected version we can test A and B. We can't test A in isolation from B but so what? Who says that we'd want to? What benefit would that give us?

Well, suppose B is not so trivial. Suppose B reads from a database and returns some value. We don't want our unit tests for A to rely on a database because A doesn't care about databases, it just cares about being able to fooB. Unfortunately, if A is the one in charge of creating B then we have no way to change that behaviour. It can only do one thing and in our production code we need it to create a B that talks to a database, so that's what we're stuck with.

However, if we were injecting the dependency then we could do this in our real code:

new A(new DatabaseB());

and inject a 'fake' or a 'mock' in our tests that acts like it's talking to a database without actually doing so:

new A(mockB);
new A(fakeB);

This allows us to use A in two different ways: with and without a database; for production code, and for test code. It gives us the flexibility to choose.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=79426&siteId=1