Dependency Injection: a discussion of the pros and cons

Dependency injection makes code more flexible and more decoupled.

  • More flexible because your class doesn’t need to know about the concrete implementation. Real life example: I was writing a bunch of unit tests, and those unit test classes needed access to a logger, so I passed a logger instance into the constructor (that is, I injected the dependency). Doing it this way paid off later. We decided it would be nice if each log message would say which test case it came from. But there were hundreds of test cases, and editing them manually would have been time consuming and tedious, which is bad all by itself, but also creates a lot of opportunity for human error. Instead, I created a TestCaseLoggerDecorator class that re-implements the logger’s interface and prepends the test case name to the log message. Then, instead of injecting the logger, I injected the decorator, and voila. Without any modification to any of the test cases, the log messages now included the test case name, because now the test cases weren’t actually invoking the logger, they were invoking the decorator.

“What is good software architecture? For me, good design means that when I make a change, it’s as if the entire program was crafted in anticipation of it. I can solve a task with just a few choice function calls that slot in perfectly, leaving not the slightest ripple on the placid surface of the code.”

  • And more decoupled because your class doesn’t need to know anything of the outside world. This goes back to the original terminology, “inversion of control.” If your class were to fetch its own dependencies, then it would need to know where to find them – whether it be a container or a singleton or a global variable or whatever – which means it would need to know about the larger application. That’s bad. If details of the larger application are baked into every class, then it’s harder to change the larger application, and almost impossible to reuse the class in different applications. But if instead dependencies are passed through the constructor, then your class doesn’t need to know or care who created it or where it came from.
5 Likes