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!
Dependency Injection is considered a design pattern and not a framework. It's one way of implementing a more general software concept called Inversion of Control ( IoC ). It's also part of SOLID Design Principles.
Dependency Injection (DI) is a software design pattern that allows us to develop loosely coupled code. DI is a great way to reduce tight coupling between software components. DI also enables us to better manage future changes and other complexity in our software.
Dependency Injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object (or client) and are made part of the client's state.
In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With