DEV Community

Jesse Phillips
Jesse Phillips

Posted on

Dependency Injection has Me Concerned

#di

I'm a big fan of dependency injection, specifically the poor man's version. However I am greatly concerned that this pattern is heavily abused when using a framework. I'm not the only one who sees this Don't Blame Dependency Injection wants to emphasize that it is not even the framework which is at fault. And when you read about the disadvantages there are similar sentiments, "don't ask if you should use dependency injection, ask what problem are you trying to solve."

Unspecified Dependencies: this is probably the worst offense for DI frameworks. You can pass a function the DI container which includes what and how to construct the interfaces needed by the function. This is nice because you can pass all the parameters in a single argument and if you need to add a new dependency then the API remains unchanged. This is also detrimental because most DI containers are not checked at Compile Time meaning your users are not informed of the API change needed to call your function. The function signature is no longer self documenting or compiler checked.

Tight Coupling to the DI Framework: If you utilize a framework and even library it can be hard not to have some form of coupling. They even have frameworks to help with that. One of the other approaches to DI is constructor injection. This is where all of the classes define the dependency in the constructor and the framework builds the tree. Here your entire dependency graph is defined by the framework, if your dependencies are deep you'll be placing DI in every situation and it will be next to impossible to call a function without the framework.

Global State: There is much written about avoiding global state and how to do it. It is one of the reasons Singleton is seen as an antipattern. With dependency injection containers things are a bit different. While frameworks could be used to build out singletons, this isn't as likely to happen. Instead the assumption is to use a global container leaving only one concrete type per interface. This is not how I view well structured code.

I think I understand those who oppose garbage collection and say it is better to handle your memory manually, a bit more. I want to say the same thing for dependencies, make it clear what is needed to complete the operation. But I started working in GC languages, but not DI frameworks.

Top comments (0)