121

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.

17
  • 5
    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, 2014 at 9:45
  • 172
    "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! Mar 13, 2014 at 15:06
  • 9
    I cannot upvote Mr Lippert's comment enough. I too found it to be confusing jargon for something I was doing naturally anyway. Mar 13, 2014 at 15:22
  • 16
    @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, 2014 at 10:52
  • 15
    @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. Mar 14, 2014 at 14:51

9 Answers 9

112

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.

3
  • 11
    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. Mar 13, 2014 at 12:41
  • 1
    @MattGibson good point. Mar 13, 2014 at 13:30
  • 2
    +1 for testing, well structured DI will help both speeding up testing and making unit tests contained within the class you are testing. Apr 5, 2014 at 19:00
54

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).

2
  • 7
    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. Mar 13, 2014 at 13:32
  • 37
    It's fun how each next simplification is more complex
    – Kromster
    Mar 14, 2014 at 5:18
50

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.

1
  • 12
    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! Mar 13, 2014 at 13:54
19

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. This assumes, of course, that all your ILightFixture implementations are designed with Liskov Substitution in mind). 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.

2
  • 1
    I wanted to say thanks, this was helpful to me, but they don't want you to do that, but rather use comments to suggest improvements, so, if you feel like it, you could add one of the other advantages you mentioned. But otherwise, thanks, this was helpful to me.
    – Steve
    Jan 19, 2018 at 15:12
  • 3
    I'm also interested in the book that you referenced, but I find it alarming that there is a 584 page book on this subject.
    – Steve
    Jan 19, 2018 at 15:19
5

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!

4

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.

2
  • 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. Mar 13, 2014 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, 2014 at 0:04
2

A lot of people said here that DI is a mechanism to out-source the initialization of an instance variables.

For obvious and simple examples you don't really need "dependency injection". You can do this by a simple parameter passing to the constructor, as you noted in question.

However, I think that a dedicated "dependency injection" mechanism is useful when you talk about application-level resources, where both caller and callee doesn't know nothing about these resources (and don't want to know!).

For example: Database connection, Security context, Logging facility, Configuration file etc.

Moreover, in general every singleton is a good candidate for DI. The more of them you have and use, the more chances you need DI.

For these kinds of resources it's quite clear that it doesn't make sense to move them all around via parameter lists and therefore the DI was invented.

Last note, you also need a DI container, that will do the actual injection... (again, to release both caller and callee from implementation details).

-2

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.

-4

This is another option in addition to amon's answer

Use Builders:

class Foo {
    private Bar bar;
    private Qux qux;

    private Foo() {
    }

    public Foo(Builder builder) {
        this.bar = builder.bar;
        this.qux = builder.qux;
    }

    public static class Builder {
        private Bar bar;
        private Qux qux;
        public Buider setBar(Bar bar) {
            this.bar = bar;
            return this;
        }
        public Builder setQux(Qux qux) {
            this.qux = qux;
            return this;
        }
        public Foo build() {
            return new Foo(this);
        }
    }
}

// in production:
Foo foo = new Foo.Builder()
    .setBar(new Bar())
    .setQux(new Qux())
    .build();

// in test:
Foo testFoo = new Foo.Builder()
    .setBar(new BarMock())
    .setQux(new Qux())
    .build();

This is what I use for dependencies. I don't use any DI framework. They get in the way.

5
  • 4
    This does not add much to the other answers from a year ago, and offers no explanation of why a builder might help the asker to understand dependency injection.
    – user22815
    Mar 4, 2015 at 21:09
  • @Snowman It is ANOTHER option in place of DI. I'm sorry you don't see it that way. Thanks for the down vote. Mar 4, 2015 at 22:00
  • 1
    the asker wanted to understand if DI really is as simple as passing a parameter, he was not asking for alternatives to DI.
    – user22815
    Mar 4, 2015 at 22:23
  • 1
    The examples of the OP are very good. Your examples provide more complexity for something that is a simple idea. They don't illustrate the issue of the question. Mar 4, 2015 at 23:32
  • Constructor DI is passing a parameter. Except you're passing an interface object rather than a concrete class object. It's this 'dependency' on a concrete implementation that is solved via DI. The constructor doesn't know that type it is being passed, neither does it care, it just knows that it is receiving a type which implements an interface. I suggest PluralSight, It has a great beginners DI/IOC course.
    – Hardgraf
    Jun 8, 2015 at 14:22

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