views:

244

answers:

8

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!

+11  A: 

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.

Rex M
thanks Adam and Rex. Yeah, Rex, could you elaborate, thanks
andy
thanks Rex, so would you say the second code example is an example of DI, assuming of course that the two parameters passed in are the ONLY dependencies?
andy
+1 after the elaboration. And a virtual +1 for "using constructors correctly."
Adam Robinson
@andy if those two objects provide all the external functionality PlayerService needs to operate, then yes it is IoC/DI
Rex M
thanks rex, but you haven't quite addressed the issue of wether a DI pattern can exists without a container. I realize my second code block isn't resolving stuff automatically, but of course it can't without a container. Are you saying a container is necessary for the ABSTRACT pattern. See Ned's answer below http://stackoverflow.com/questions/3145764/is-dependency-injection-a-pattern-and-is-this-it/3145786#3145786
andy
@andy I don't think a container is necessary at all (see my last edit), but I think that may not be a universal opinion.
Rex M
@Rex M: Well, what is giving you the DBConnection dependency, if not a container? Something must be able to resolve the intention into a concrete type and pass it to the constructor. Even if this is hand written code, in some kind of class which creates `Foo`, it seems hard to me to argue that that constructing class is not a container of the depended type, whatever the shape.
codekaizen
@codekaizen That is true, the caller could be considered the "container". My point is - if we expand the definition of "what is a container?" to be "anything outside the class receiving the injection" then it seems redundant to even define it.
Rex M
@Rex M: This is true, expanding definitions tends to have this inclusive effect, however, in this case perhaps there is some utility to it. The essential part to understand is the resolution of a "requested" dependency into an object of a concrete type, and delegating the responsibility for the lifetime of that dependency to another class. If we think of this as a container, we can begin to appreciate how it might be useful to have the container substitute different concrete implementations depending on the runtime requirements, e.g., during a unit testing run vs. production run.
codekaizen
I agree with Rex. It's something external constructing the dependencies and passing/setting them into the object, rather than the object constructing/controlling them itself, that I think is the essence of DI.
Owen S.
@code4life: Martin Fowler did not coin the term. I think Ralph Johnson did. Martin Fowler just points out that "inversion of control" is a common pattern found in all frameworks, where the user code is called by the framework.
codekaizen
@Owen S.: Would you go so far as to say that any object passing a value to a constructor or setting a property is a DI pattern? It seems a bit silly, to me. I think that we can't disregard the removal of explicit code to satisfy the dependency as a critical element of a true DI system. This is what "injection" seems to try to convey - that the dependency appears inside the depending class without having to know about the surface.
codekaizen
code4life
@codekaizen: Yes, I would – I think of DI as a pretty trivial pattern in its essence, as many patterns are. But you'd only bother to call it DI if the dependencies you were injecting were actually significant in some way. It's how you use it to create flexibility and maintainability in your code that ultimately signifies, not the pattern's name, or the whizzy frameworks you use to manage the additional complexity that it entails.
Owen S.
wow, great discussion guys! It's quite an interesting topic huh, and yes, in it's essence it's quite a simple but powerful pattern. I tend to agree with @Rex in terms of the dangers of applying such a loose definition to "Container", but all points are valid
andy
marked another question as the answer, see the comments on that answer as to the why, although they were both excellent answers.
andy
+2  A: 

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.

Ned Batchelder
I agree Ned... noone seems to have addressed that??
andy
+1 Nice explanation.
David Relihan
It might seem "controversial" to mark this as the Answer, but I feel Ned here has essentially said what Rex had said, but more simply, and more focused on the question... although they are both excellent answers.
andy
+1  A: 
  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.

Marc Bollinger
thanks marc. but in response to my question 2... how would you do that without a container? That's really my question
andy
Glurp. Ned's is actually a very good point. I was focusing on your composition of the objects all at one shot, and not on the fact that you're deferring construction of the client and skin client to outside the construction of the service. Rescinding that part.
Marc Bollinger
A: 

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.

codekaizen
agreed, but that assumes a container. I realize this but am asking, can DI exist without a container, and how
andy
@andy: My point is, not really. If you think about this relationship, something needs to wire up that concrete class. What is going to do it? Something that can resolve the types which are depended on and pass them to the depending type. This is a container, whatever shape it might take.
codekaizen
A: 

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.

Will Marcouiller
+4  A: 

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.

Bryan Ash
+1 Simple and clear, lean and swift, just like we like them! =)
Will Marcouiller
agreed, I'm not sure why the first answer got so many upvotes compared to the others..??
andy
+1  A: 

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.

Mark Seemann
great answer, thanks, I'll check out your blog
andy