Skip to content

Instantly share code, notes, and snippets.

@r00k
Created July 13, 2012 13:58
Show Gist options
  • Save r00k/3105024 to your computer and use it in GitHub Desktop.
Save r00k/3105024 to your computer and use it in GitHub Desktop.
Dependency Injections Pros/Cons/Questions

Dependency Injection

Pros

  • 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.

Cons

  • 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.

Questions:

  • 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?
@rustygeldmacher
Copy link

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".

@r00k
Copy link
Author

r00k commented Jul 16, 2012

tuker (and others) - I'm not sure I love the idea of providing a default value for the injected dependencies.

Since the default can be overridden, you still need to check the calling code to see whether it is. As such, you haven't addressed the issue of needing to check multiple files to be sure what's happening.

I suppose I'd prefer DI with a default specified to hard-coding a dependency though.

@jgn
Copy link

jgn commented Jul 16, 2012

It depends on what you mean by: "See what's happening."

Surely we are imagining that there are multiple implementations that might be injected. By that reasoning, to check all "known" / in hand implementations, you're going to have to go to other files or inspect the tests.

But to "see what's happening" in the narrow compass of the implicit expectations of a basic implementation, a default implementation could help quite a bit.

I would guess that since we like small focused classes with limited responsibilities, any default implementation is not going to be a HUGE amount of code.

@dreoliv
Copy link

dreoliv commented Jul 16, 2012

@r00k
I think what you're pointing against DI is a "problem" with duck-typing in general. You never know if some parameter you received is exactly what you where expecting, and the only way to "see what's happening" is checking the calling code and/or searching for the instantiation of such object.

The inappropriate quotes surrounding "problem" are due to the fact that it's not really a problem, just a trade-off made by the language designers.

@jferris
Copy link

jferris commented Jul 16, 2012

@abernardes All of these abstractions and indirections are tradeoffs, duck typing and dependency injection included. They provide software that is easier to change overall and easier to understand at the unit level, but harder to understand as a whole system. Every class you abstract is another opportunity to name something and create a small, comprehensible unit, but it's also another hop the reader has to make to follow the path of the program. Flat, procedural programming is easy to follow but impossible to change, and the lack of abstractions and naming makes the "what" obvious but the "why" impossible to divine. In short, you need to find the right balance between abstracting yourself into a puzzle and creating a cemented mess of procedural glue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment