- Classes are more modular, as they depend only on the interface of passed-in dependencies. Class behavior can be changed by swapping out a new component.
- Testing is simplified, since stubs can be substituted for any dependency.
- It's harder to understand how a class works when reading just that class. You may have to track down its invocation to see what kind of components are passed in.
- Is DepedencyClass.expects(:new).returns(stub)) a smell, since we should have injected that stub to the class that uses it instead?
- If a class uses DI, should one only pass in already-instantiated dependencies, or is it okay to let the calling class instantiate them?
- Am I missing any pros or cons?
I love IOC and DI, and have used the practice extensively in my C# days to make flexible systems that are easy to test and can be adapted to client requirements.
One thing I learned, however, is that overusing or misusing DI can lead to a "class explosion", where you have a myriad tiny classes that all do one small thing and only exist to be injected into the "real" objects of the system... It may end up proving difficult to figure out what the system in its entirety is trying to accomplish simply by looking at the classes. Further, the configuration of the system (think XML configuration in Spring) can end up being so opaque that when you want to adjust behavior, it's almost impossible to figure out where to start modifying the configuration.
Not making a case against DI, but those are some pitfalls I'd consider "cons".