When to use Dependency Injection? When not to?
From what I understand, the trade-off here is a matter of added complexity. Maybe?
It se开发者_如何学Goems (always?) more decoupled to use Dependency Injection, but simpler (to many people) without it.
From what I understand about everything in life, nothing is absolute, and there's a time and place for everything. I'm trying to understand the trade-offs here.
Dependency Injection when done correctly (effectively?) certainly does decouple your objects. In my opinion the area where this benefit is realised most is when you use Mock or stub objects in your unit tests. Quite often this means that you will be unit testing less in each individual test, thus making them simpler. This promotion of effective unit tests then often brings its own additional benefits.
I wouldn't necessarily say that DI adds complexity because if the design of a system is inelegant it will be complex whether you use DI or not. It may however add an additional learning curve if you use a DI framework for the first time, the Spring framework for instance.
Use Dependency Injection when you want to create alternative implementations of a given service type. The canonical example of this is substituting a mock object in place of a service provider for testing purposes.
For example, Dependency Injection allows you to use a "real" database, or a "fake" database that mimics the behavior of the real database. In both cases, the dependency being "injected" has the same interface, but you can swap out the implementation.
In practice, I find dependency-injection based designs are, while slightly more verbose, a lot easier to deal with because there is more control, less coupling between classes, more flexibility with implementation and allows wider use of existing classes throughout an application.
It depends on how clearly defined or intuitive the dependencies are as well. Coming from a native C++ background, I've found parts in .NET where the dependencies where are plainly obvious and provided a lot of flexibility, but other areas that I just didn't understand at all and couldn't immediately understand the requirements to use a certain piece of code or object, due to a variety of factors including class naming and my knowledge of the system.
I say, if you're going to design your code with dependency injection in mind, just try to make the dependencies as clear and intuitive as possible.
That's my idea of it anyhow.
There is a broad spectrum covered by "dependency injection," from passing in constructor parameters to an XML-configured framework. One happy medium I recently "discovered" covers many of the "mock" cases without needing an actual framework. It's a little bit subversive but is much easier to work with in isolated cases.
You override a factory method inside your main code to run tests with a faked service. Basically it's a tradeoff between abuse of inheritance (with this method) and abuse of configuration (with frameworks). Either way it's "dependency injection," or as we in the real world like to call it, parameterization.
Main code:
public class A {
// ...
private service;
protected Service getService() {
return new RealService();
}
public A() {
service = getService();
}
// ...
}
Test code:
public class Test {
void test() {
final Service fakeService = new FakeService();
A thingToTest = new A() {
protected Service getService() { return fakeService; }
}
thingToTest.doOneThing();
// ...
}
}
精彩评论