Reputation: 8875
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.
So, can DI be used as just a pattern without any extra frameworking?
If so, is the above code an example of it?
Lastly, what defines a DI pattern, if it exists, without the notion of a Container.
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
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
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
Reputation: 3119
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".
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.
As mentioned, Martin Fowler's is the canonical definition, and is pretty well covered elsewhere.
Upvotes: 1
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
Reputation: 24132
Here are some other articles that might bring some other important details on the subject, in order of "should-be-read-first":
After having read these, I found myself a better understanding of the subject.
Upvotes: 0
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
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:
Yes, DI can be accomplished without a framework.
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".
See above.
Upvotes: 3
Reputation: 2109
You should have a read of this: http://dotnetslackers.com/articles/designpatterns/InversionOfControlAndDependencyInjectionWithCastleWindsorContainerPart1.aspx
Upvotes: 0