Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm reading about dependency injection (DI). To me, it is a very complicated thing to do, as I was reading it was referencing inversion of control (IoC) as well and such I felt I was going to be in for a journey.

This is my understanding: Instead of creating a model in the class which also consumes it, you pass (inject) the model (already filled with interesting properties) to where it is needed (to a new class which could take it as a parameter in the constructor).

To me, this is just passing an argument. I must have miss understood the point? Maybe it becomes more obvious with bigger projects?

My understanding is non-DI (using pseudo code):

public void Start()
{
    MyClass class = new MyClass();
}

...

public MyClass()
{
    this.MyInterface = new MyInterface(); 
}

And DI would be

public void Start()
{
    MyInterface myInterface = new MyInterface();
    MyClass class = new MyClass(myInterface);
}

...

public MyClass(MyInterface myInterface)
{
    this.MyInterface = myInterface; 
}

Could some one shed some light as I'm sure I'm in a muddle here.

share|improve this question
3  
Try having 5 of the MyInterface and MyClass AND have multiple classes forming a dependency chain. It becomes a pain in the butt to set up everything. –  Euphoric yesterday
54  
"To me, this is just passing an argument. I must have misunderstood the point?" Nope. You got it. That's "dependency injection". Now see what other crazy jargon you can come up with for simple concepts, it's fun! –  Eric Lippert yesterday
3  
I cannot upvote Mr Lippert's comment enough. I too found it to be confusing jargon for something I was doing naturally anyway. –  Alex Humphrey yesterday
3  
@EricLippert: While correct, I think that's slightly reductive. Parameters-as-DI isn't an immediately straightforward concept for your average imperative/OO programmer, who's used to passing data around. DI here is letting you pass behaviour around, which requires a more flexible worldview than a mediocre programmer will have. –  Phoshi 18 hours ago
2  
@Phoshi: You make a good point, but you've also put your finger on why I am skeptical that "dependency injection" is a good idea in the first place. If I write a class that depends for its correctness and performance on another class's behaviour then the last thing I want to do is make the user of the class responsible for correctly constructing and configuring the dependency! That's my job. Every time you let a consumer inject a dependency you create a point where the consumer might do it wrong. –  Eric Lippert 14 hours ago
show 6 more comments

6 Answers

Well yes, you inject your dependencies, either through a constructor or through properties.
One of the reasons for this, is not to encumber MyClass with the details of how an instance of MyInterface needs to be constructed. MyInterface could be something that has a whole list of dependencies by itself and the code of MyClass would become ugly very fast if you had instantiate all the MyInterface dependencies inside of MyClass.

Another reason is for testing.
If you have a dependency on a file reader interface and you inject this dependency through a constructor in, say, ConsumerClass, that means that during testing, you can pass an in-memory implementation of the file reader to the ConsumerClass, avoiding the need to do I/O during testing.

share|improve this answer
6  
This is great, well explained. Please accept an imaginary +1 since my rep won't allow it yet! –  MyDaftQuestions yesterday
7  
The complicated construction scenario is a good candidate for use of the Factory pattern. That way, the factory takes on the responsibility of constructing the object, so that the class itself doesn't have to and you stick to the single responsibility principle. –  Matt Gibson yesterday
 
@MattGibson good point. –  Stefan Billiet yesterday
add comment

How DI can be implemented depends very much on the language used.

Here is a simple non-DI example:

class Foo {
    private Bar bar;
    private Qux qux;

    public Foo() {
        bar = new Bar();
        qux = new Qux();
    }
}

This sucks, e.g. when for a test I want to use a mock object for bar. So we can make this more flexible and allow instances to be passed via the constructor:

class Foo {
    private Bar bar;
    private Qux qux;

    public Foo(Bar bar, Qux qux) {
        this.bar = bar;
        this.qux = qux;
    }
}

// in production:
new Foo(new Bar(), new Qux());
// in test:
new Foo(new BarMock(), new Qux());

This already is the most simple form of dependency injection. But this still sucks because everything has to be done manually (also, because the caller can hold a reference to our internal objects and thus invalidate our state).

We can introduce more abstraction by using factories:

  • One option is for the Foo to be generated by an abstract factory

    interface FooFactory {
        public Foo makeFoo();
    }
    
    class ProductionFooFactory implements FooFactory {
        public Foo makeFoo() { return new Foo(new Bar(), new Baz()) }
    }
    
    class TestFooFactory implements FooFactory {
        public Foo makeFoo() { return new Foo(new BarMock(), new Baz()) }
    }
    
    FooFactory fac = ...; // depends on test or production
    Foo foo = fac.makeFoo();
    
  • Another option is to pass a factory to the constructor:

    interface DependencyManager {
        public Bar makeBar();
        public Qux makeQux();
    }
    class ProductionDM implements DependencyManager {
        public Bar makeBar() { return new Bar() }
        public Qux makeQux() { return new Qux() }
    }
    class TestDM implements DependencyManager {
        public Bar makeBar() { return new BarMock() }
        public Qux makeQux() { return new Qux() }
    }
    
    class Foo {
        private Bar bar;
        private Qux qux;
    
        public Foo(DependencyManager dm) {
            bar = dm.makeBar();
            qux = dm.makeQux();
        }
    }
    

The remaining problems with this are that we need to write a new DependencyManager subclass for each configuration, and that the number of dependencies which can be managed is fairly restricted (each new dependency needs a new method in the interface).

With features like reflection and dynamic class loading we can circumvent this. But this depends very much on the language used. In Perl, classes can be referenced by their name, and I could just do

package Foo {
    use signatures;

    sub new($class, $dm) {
        return bless {
            bar => $dm->{bar}->new,
            qux => $dm->{qux}->new,
        } => $class;
    }
}

my $prod = { bar => 'My::Bar', qux => 'My::Qux' };
my $test = { bar => 'BarMock', qux => 'QuxMock' };
$test->{bar} = 'OtherBarMock';  # change conf at runtime

my $foo = Foo->new(rand > 0.5 ? $prod : $test);

In languages like Java, I could have the dependency manager behave similar to a Map<Class, Object>:

Bar bar = dm.make(Bar.class);

To which actual class the Bar.class is resolved can be configured at runtime, e.g. by maintaining an Map<Class, Class> which maps interfaces to implementations.

Map<Class, Class> dependencies = ...;

public <T> T make(Class<T> c) throws ... {
    // plus a lot more error checking...
    return dependencies.get(c).newInstance();
}

There is still a manual element involved in writing the constructor. But we can make the constructor completely unnecessary, e.g. by driving the DI via annotations:

class Foo {
    @Inject(Bar.class)
    private Bar bar;

    @Inject(Qux.class)
    private Qux qux;

    ...
}

dm.make(Foo.class);  // takes care of initializing "bar" and "qux"

Here is an example implementation of a tiny (and very restricted) DI framework: http://ideone.com/b2ubuF, although this implementation is completely unusable for immutable objects (this naive implementation cannot take any parameters for the constructor).

share|improve this answer
5  
This is super with great examples, although it is going to take me a few times of reading it to digest it all, but thanks for taking so much time. –  MyDaftQuestions yesterday
5  
It's fun how each next simplification is more complex –  Krom Stern 23 hours ago
add comment

Our friends on Stack Overflow have a nice answer to this. My favourite is the second answer, including the quote:

"Dependency Injection" is a 25-dollar term for a 5-cent concept. (...) Dependency injection means giving an object its instance variables. (...).

from James Shore's blog. Of course, there are more complex versions / patterns layered on top of this, but it is enough to basically understand what is going on. Instead of an object creating its own instance variables, they are passed in from outside.

share|improve this answer
5  
I had read this... and until now, it made no sense... Now, it makes sense. Dependency isn't actually that big a concept to understand (regardless of how powerful it is) but it does have a big name and a lot of internet noise associated with it! –  MyDaftQuestions yesterday
add comment

Let's say you are doing the interior design in your living room: you install a fancy chandelier on your ceiling and plug in a classy matching floor lamp. A year later your lovely wife decides she'd like the room a little less formal. Which lighting fixture is going to be easier to change?

The idea behind DI is to use the "plug-in" approach everywhere. This may not seem like a big deal if you live in a simple shack with no drywall and all the electrical wires exposed. (You're a handyman -- you can change anything!) And similarly, on a small & simple application, DI can add more complication than it is worth.

But for a large and complex application, DI is indispensable for long-term maintenance. It allows you to "unplug" entire modules from your code (the database backend, for example), and exchange them with different modules that accomplish the same thing but do it in an entirely different way (a cloud storage system, for example).

BTW, a discussion of DI would be incomplete without a recommendation of Dependency Injection in .NET, by Mark Seeman. If you are familiar with .NET and you ever intend to be involved in large-scale SW development, this is an essential read. He explains the concept far better than I can.

Let me leave you with one last essential characteristic of DI that your code example overlooks. DI allows you to harness the vast potential of flexibility that is encapsulated in the adage "Program to interfaces". To modify your example slightly:

public void Main()
{
    ILightFixture fixture = new ClassyChandelier();
    MyRoom room = new MyRoom (fixture);
}
...
public MyRoom(ILightFixture fixture)
{
    this.MyLightFixture = fixture ; 
}

But NOW, because MyRoom is designed to the ILightFixture interface, I can easily go in next year and change one line in the Main function ("inject" a different "dependency"), and I instantly get new functionality in the MyRoom (without having to rebuild or redeploy MyRoom, if it happens to be in a separate library). All, with just a simple change:

public void Main()
{
    ILightFixture fixture = new MuchLessFormalLightFixture();
    MyRoom room = new MyRoom (fixture);
}

Plus, I can now Unit Test MyRoom (you are unit testing, right?) and use a "mock" light fixture, which allows me to test MyRoom entirely independent of ClassyChandelier.

There are many more advantages, of course, but these are the ones that sold the idea to me.

share|improve this answer
 
well said +1, I think the Interface benefit is massive. It has made my solutions a lot easier to maintain and tweak as the base data model changes according to the client's needs. –  J King yesterday
 
why hasn't this answer got more votes? It's a lot better than most of the ones that have downgraded the usefulness of DI. Sadly I can only give one vote! –  Avrohom Yisroel 13 hours ago
add comment

Dependency injection is just passing a parameter, but that still leads to some issues, and the name is intended to focus a bit on why the difference between creating an object vs. passing one in is important.

It's important because (pretty obviously) any time object A calls type B, A is dependent on how B works. Which means that if A makes the decision of specifically which concrete type of B it will use, then a lot of flexibility in how A can be used by outside classes, without modifying A, has been lost.

I mention this because you talk about "missing the point" of dependency injection, and this is much of the point of why people like to do it. It may just mean passing a parameter, but whether you do so can be important.

Also, some of the difficulty in actually implementing DI does show up better in large projects. You will generally move the actual decision of which concrete classes to use all the way out to the top, so your start method might look like:

public void Start()
{
    MySubSubInterfaceA mySubSubInterfaceA = new mySubSubInterfaceA();
    MySubSubInterfaceB mySubSubInterfaceB = new mySubSubInterfaceB();     
    MySubInterface mySubInterface = new MySubInterface(mySubSubInterfaceA,mySubSubInterfaceB);
    MyInterface myInterface = new MyInterface(MySubInterface);
    MyClass class = new MyClass(myInterface);
}

but with another 400 lines of this kind of riveting code. If you imagine maintaining that over time the appeal of DI containers becomes more apparent.

Also, imagine a class that, say, implements IDisposable. If the classes that use it get it via injection rather than creating it themselves, how do they know when to call Dispose()? (Which is another issue that a DI container deals with.)

So, sure, dependency injection is just passing a parameter, but really when people say dependency injection they mean "passing a parameter to your object vs. the alternative of having your object instantiate something itself", and dealing with all the benefits of drawbacks of such an approach, possibly with the help of a DI container.

share|improve this answer
 
That's a lot of subs and interfaces! Do you mean to new up an interface instead of a class which implements the interface? Seems wrong. –  JBRWilkinson yesterday
 
@JBRWilkinson I mean a class that implements an interface. I should make that clearer. However, the point is that a large app will have classes with dependencies that in turn have dependencies that in turn have dependencies... Setting it all up manually in the Main method is the result of doing lots of constructor injection. –  psr yesterday
add comment

If you pass in an abstract reference type then the calling code can pass in any object that extends/implements the abstract type. So in future the class that uses the object could use a new object that has been created without ever modifying its code.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.