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
4  
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 Mar 13 at 9:45
109  
"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 Mar 13 at 15:06
8  
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 Mar 13 at 15:22
10  
@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 Mar 14 at 10:52
9  
@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 Mar 14 at 14:51

7 Answers 7

up vote 81 down vote accepted

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
9  
This is great, well explained. Please accept an imaginary +1 since my rep won't allow it yet! –  MyDaftQuestions Mar 13 at 10:00
9  
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 Mar 13 at 12:41
    
@MattGibson good point. –  Stefan Billiet Mar 13 at 13:30
    
+1 for testing, well structured DI will help both speeding up testing and making unit tests contained within the class you are testing. –  Umur Kontacı Apr 5 at 19:00

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 Mar 13 at 13:32
13  
It's fun how each next simplification is more complex –  Krom Stern Mar 14 at 5:18

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
8  
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 Mar 13 at 13:54

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

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 Mar 13 at 23:31
    
@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 Mar 14 at 0:04

At the class level, it is easy.

'Dependency Injection' simply answers the question "how will I find my collaborators" with "they are pushed at you - you don't have to go and get them yourself". (It is similar to - but not the same as - 'Inversion of Control' where the question "how will I order my operations over my inputs?" has a similar answer).

The only benefit that having your collaborators pushed at you is that enables client code to to use your class to compose an object graph which suits its present need ... you have not arbitrarily pre-determined the shape and mutability of the graph by privately deciding the concrete types and life-cycle of your collaborators.

(All those other benefits, of testability, of loose coupling, etc, follow largely from the use of interfaces and not so much from the dependency-injection-ness, although DI does naturally promote the use of interfaces).

It is worth noting that, if you do avoid instantiating your own collaborators, your class must therefore get its collaborators from a constructor, a property, or a method-argument (this latter option is often overlooked, by the way ... it does not always make sense for a class' collaborators to be a part of its 'state').

And that's a good thing.

At the application level ...

So much for the per-class view of things. Let's say you have a bunch of classes which follow the "do not instantiate your own collaborators" rule, and wish to make an application from them. The simplest thing to do is to use good old code (a really useful tool for invoking constructors, properties, and methods!) to compose the object graph you want, and throw some input at it. (Yes, some of those objects in your graph will themselves be object-factories, which have been passed around as collaborators to other long-lived objects in the graph, ready for service ... you can't pre-construct every object!).

... your need to 'flexibly' configure your app's object-graph ...

Depending on your other (non-code-related) objectives, you might want to give the end-user some control over the object graph thus deployed. This leads you in the direction of a configuration scheme, of one sort or another, whether it be a text file of your own design with some name/value pairs, an XML file, a custom DSL, a declarative graph-description language such as YAML, an imperative scripting language such as JavaScript, or something else appropriate to the task at hand. Whatever it takes to compose a valid object graph, in a way that meets the needs of your users.

... may be a significant design force.

In the most extreme circumstance of that type, you could elect to take a very general approach, and give end users a general mechanism for 'wiring up' the object-graph of their choosing and even allow them to provide concrete realizations of interfaces to the runtime! (Your documentation is a gleaming jewel, your users are very smart, familiar with at least the coarse outline of your application's object graph, but don't happen to have a compiler handy). This scenario can theoretically occur in some 'enterprise' situations.

In that case, you probably have a declarative language which allows your users to express any type, the composition of an object graph of such types, and a palette of interfaces which the mythical end-user can mix and match. To reduce the cognitive load on your users, you prefer a 'configuration by convention' approach, so that they only have to step in and over-ride the object-graph-fragment of interest, instead of wrestling with the whole thing.

You poor sod!

Because you didn't fancy writing up all that yourself (but seriously, check out a YAML binding for your language), you are using a DI framework of some kind.

Depending on the maturity of that framework, you may not have the option of using constructor-injection, even when it makes sense (the collaborators don't change over the lifetime of an object), thereby forcing you to use Setter Injection (even when collaborators don't change over the lifetime of an object, and even when there is not really a logical reason why all concrete implementations of an interface must have collaborators of a specific type). If so, you are currently in strong-coupling hell, despite having diligently 'used interfaces' throughout your code-base - horror!

Hopefully though, you used a DI framework which gives you option of constructor injection, and your users are only a bit grumpy at you for not spending more time thinking about the specific things they needed to configure and giving them a UI more suited to the task at hand. (Although to be fair, you probably did try to think of a way, but JavaEE let you down and you had to resort to this horrible hack).

Bootnote

At no point are you ever using Google Guice, which gives you the coder a way to dispense with the task of composing an object-graph with code ... by writing code. Argh!

share|improve this answer

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

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.