andy
andy

Reputation: 8875

Is Dependency Injection a pattern and, is this it?

I was having a heated debate with one of my colleagues on dependency injection, and realized I didn't quite know all the facts on the subject.

So, take this code (just so you know,we're using Castle Windsor)

IPlayerService service = Container.Resolve<IPlayerService>();

The above code is obviously an example of DI using an IoC.

However, see the code below (UPDATE: Assume I'm passing ALL external dependencies through the constructor):

var playerClient = new PlayerClient();
var playerSkinClient = new PlayerSkinClient();
IPlayerService service = new PlayerService(playerClient, playerSkinClient);

My contention was that the above code was an example of DI pattern, and that DI can exist without an IoC.

Now, my colleague didn't completely disagree with my point, but he said that the above code is not example of any pattern involving DI.

  1. So, can DI be used as just a pattern without any extra frameworking?

  2. If so, is the above code an example of it?

  3. Lastly, what defines a DI pattern, if it exists, without the notion of a Container.

UPDATE

I'll be going through the answers and comments more thoroughly later tonight, but just wanted to thank everyone for the well thought out answers and comments so far!

Upvotes: 14

Views: 1344

Answers (8)

Mark Seemann
Mark Seemann

Reputation: 233125

The funny thing is that the first example isn't DI at all, but an example of the Service Locator anti-pattern - nothing is injected.

Your own example is pure DI - more specifically an implementation of the Constructor Injection pattern.

DI is not one pattern, but a collection of patterns and principles. When we wire up all dependencies by hand we normally call it Poor Man's DI. In other words, DI Containers are strictly optional, but highly recommended :)

See also this description of what a DI Container brings to the table.

Upvotes: 1

Bryan Ash
Bryan Ash

Reputation: 4479

So, can DI be used as just a pattern without any extra frameworking?

Yes, absolutely.

If so, is the above code an example of it?

Yes, absolutely.

Lastly, what defines a DI pattern, if it exists, without the notion of a Container.

An object is given everything it depends on; its dependancies are injected into it.

Upvotes: 4

Marc Bollinger
Marc Bollinger

Reputation: 3119

  1. Yes, though compared with something like PicoContainer--or other really tiny containers, all of which are tested and well thought-out--you're going to wind up implementing the same set of features, in the end. The best example of this is Ayende's "Building an IoC container in 15 lines".

  2. Revising my answer, I'm going to switch to yes. I think the main cognitive dissonance here is that due to developers conflating the fact that many/most DI/IoC frameworks offer neat ways to construct objects that don't look like new, that's what makes them adhere to IoC ideas.

  3. As mentioned, Martin Fowler's is the canonical definition, and is pretty well covered elsewhere.

Upvotes: 1

Rex M
Rex M

Reputation: 144112

According to Martin Fowler, who is something of an expert on the subject, Dependency Injection is another name for the concrete implementation of the abstract concept known as Inversion of Control (full article).

At its root, all DI means is: the objects which a class depends on to work correctly are initialized and passed into it externally, rather than the class itself being responsible for acquiring/initializing those objects. The specifics of how this is accomplished is beyond the scope of the pattern.

IoC is the same thing, but as Martin Fowler says, saying "Inversion of Control" is a very obtuse way of describing what is happening.

Personally I don't think "Dependency Injection" is much better though. I would describe it as "using constructors correctly".

Example of non-IoC/non-DI:

class Foo
{
    void DoSomething()
    {
        DbConnection myConnection = new DbConnection(ConfigurationSettings...);
        myConnection.ExecuteCommand();
    }
}

Same thing using IoC/DI:

class Foo
{
    private DbConnection myConnection;

    public Foo(DbConnection conn)
    {
        myConnection = conn;
    }

    void DoSomething()
    {
        myConnection.ExecuteCommand();
    }
}

I respectfully disagree with those who argue it isn't real IoC/DI unless you have an explicit binder/assembler/what-have-you that connects the injected types with the concrete implementations, because the class receiving the dependencies doesn't know the difference. Whether you arrange the dependencies in an external class or an external config file is an implementation detail.

Upvotes: 15

Will Marcouiller
Will Marcouiller

Reputation: 24132

Here are some other articles that might bring some other important details on the subject, in order of "should-be-read-first":

  1. Dependency Injection Demystified;
  2. Dependency injection.

After having read these, I found myself a better understanding of the subject.

Upvotes: 0

codekaizen
codekaizen

Reputation: 27419

This really isn't an example of DI.

The reason is you are arranging the dependencies (PlayerClient and PlayerSkinClient in your case), instead of having the dependencies arranged for you (passed in by the container when constructing a concrete IPlayerService). This is the "inversion of control" - you have the constructor called, instead of calling it. This is the main reason for using a DI pattern, and having a container which scopes, resolves and puts the dependencies into the objects that request them is the concrete way to do this.

When you let a container manage this passing of dependencies, you don't need to write and maintain the code that passes the dependencies to the concrete IPlayerService. This allows you to make other implementations of PlayerClient and PlayerSkinClient (for example, when you want to mock them for building tests) and not have to update the code which initializes the IPlayerService. This is why the DI pattern is useful.

Upvotes: 0

Ned Batchelder
Ned Batchelder

Reputation: 375484

In the Java world, dependency injection often involves a framework, a container, and so on. But there's no need for all that machinery.

The essence of dependency injection is a class being able to be assigned objects it depends upon rather than having them hard-coded in the implementation. If you can "inject" those "dependencies" from outside the class, then you have dependency injection. A framework may be a good way to do this, but it isn't required.

In the Python world, there is no culture of frameworks for dependency injection, so many programmers there wonder what all the fuss is about. To them, DI is "just" being able to pass objects or classes into constructors.

To answer your specific question:

  1. Yes, DI can be accomplished without a framework.

  2. Yes, the above code is an example of it: PlayerService has no knowledge of where the PlayerClient or PlayerSkinClient come from. They've been injected into the class. Note that others here have answered this "No".

  3. See above.

Upvotes: 3

Related Questions