Dependency Injection Inversion Rejection
In Uncle Bob’s blog on dependency injection, Dependency Injection Inversion, he says that “you should carefully restrict how and where you use [dependency frameworks].” While I don’t necessarily disagree with the statement itself, I do have some concerns about his reasoning and his general view on DI.
The first concern I have is that his general idea and purpose of DI is not accurate, in my opinion. He stated that “the goal of these frameworks is to help you create instances without having to resort to new or factories”. In my opinion, that is not at all what dependency injection is about. Dependency injection is about, as its name suggests, removing dependencies from your code, decoupling your code, making it more maintainable, and testable, among other things. His examples didn’t show why someone would ever use DI. As he stated “My goal is to create an instance of BillingService.” While I agree with his purpose for writing the blog, that you shouldn’t use something just because its new, everyone is talking about it, or without reason, I just really feel like his example missed the point. I can make a really good argument of why you shouldn’t use any particular pattern, such as MVC/MVVM or Decorator, etc, if I show you an example that doesn’t show the pattern’s value or purpose.
Also, I wasn’t sure of the reasoning for suggesting to use instances or factories in his example? I think he was trying to make it so he didn’t have to use “Guice” (which is the DI framework he uses) all over his code.
BillingService.factory = new BillingServiceFactory(injector);
// Deep in the bowels of my code.
BillingService billingService = BillingService.factory.make();
??
As I stated, the goal is NOT to stop or reduce using new (although it is a side effect of the pattern but not the purpose), and you don’t have to use singletons or factories. I extremely dislike that solution because you are changing the way you design/implement your classes based on the fact that you use a DI framework, which I think is wrong. Not only that but it would be really cumbersome to make a factory for each class that you want to use DI with. The point is to reduce dependencies between concrete classes and program to an interface. So if you don’t want that framework all over your code, which i wouldn’t want either because that creates a dependency which is the opposite of what we are trying to do, I would create a wrapper for the DI framework. That way the application would not depend on the framework and it can be swapped out with another. Now you don’t have factories or instances everywhere and you are not tied to a DI framework. This also brings up another issue. I’m not sure I agree with frameworks that use attributes or annotations inside the classes you are trying to inject on. For example, Guice (Java) requires the @inject annotation and Ninject (.NET) requires the [Inject] attribute on the constructor of your class. This creates a dependency on the framework and besides that you should never have to pollute your code with these kinds of things (those classes should have no knowledge that they are being instantiated by a framework and should not be required to).
His example is in Java, where as I come from the .NET world so i am not familiar with DI frameworks in Java. For .NET, one of the most popular frameworks is Castle Windsor, and you can find an excellent in-depth explanation of DI and Inversion of Control using this framework here.