Dependency injection is a million dollars name for a 5 cents concept. Most developers I have interviewed can’t explain in simple words what DI really is. When I say that DI is just passing dependency as an argument to function – they often become very surprised. They expect DI to be something much more than that, but in reality it isn’t.
If you don’t want to add more arguments to support DI, you may use partial application in languages that support it, like OCaml, or use so-called builder pattern. Here is a pseudocode, that explains what I mean:
// instead of myFunc(di1, d12, arg1, arg2) // you need to provide two interfaces // one for the component construction: myFunc := buildMyFunc(di1, di2) // and one for the component itself: myFunc(arg1, arg2)
This approach also helps to follow Single Responsibility Principle, because the
myFunc component is now responsible only for what we need from it. Also now we only have one place (or any number of places we want) to configure a component with proper dependencies that we want to use for the particular environment or circumstances.
When I hear about Dependency Injection frameworks or that some framework offers dependency injection functionality I really become frustrated by people and software engineers in particular. Good news about all those people – they will all be fucked by the complexity they bring to projects and by the lack of understanding what dependency injection actually is and how simple it really is.
Another issue with Dependency Injection
Developers often get obsessed with it. People tend to use it everywhere even if there is no need for dependency replacement. They just apply DI by default for the sake of flexibility, that can easily be added any time later using the pattern mentioned above.
In reality dependency injection should be a stupid simple tactic for the situations when flexibility via configurability becomes a real requirement. For example, when you work on hot point performance optimisation and want to a/b test two implementations of some component. In that case you can apply DI, test and then remove DI and leave the better implementation.
Some more notes on implementation
It is not required, but desirable to have dependency in a local variable. You can also use package level or global variables for dependency injections. The only requirement here is that you must understand what you do and why you picked one approach over another.