• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Junilu Lacar
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Piet Souris
  • Carey Brown
  • Stephan van Hulst
Bartenders:
  • Frits Walraven
  • fred rosenberger
  • salvin francis

Dependency Injection vs Implementation Leakage

 
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,
My co-worker and I have been having some conversations about an implementation and could use some help.
I have a class called RulesEvaluator which has some business logic. This class needs some reference data which is available in another class called ReferenceDataHelp. (The ReferenceDataHelp gets the data from a database if it matters).

So now I have the caller code which instantiates the RulesEvaluator and calls a method called runRules on it. All good so far ! Now my question is how should ReferenceDataHelp class be thought of ? I'm thinking it as an implementation detail that only the RulesEvaluator class needs to know and hence the object of ReferenceDataHelp should be instantiated from within the class or the method.
However my co-worker thinks, the ReferenceDataHelp should be instantiated by the caller code and dependency injected into RulesEvaluator to allow for unit testing.
 
Marshal
Posts: 16440
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If it makes it easier to unit test, I would favor that approach. That said, there are other way besides dependency injection that you can create seams in your design that allows for unit testing. One way is to keep that ReferenceDataHelp class in a separate deployment unit, e.g. JAR file. You can have one JAR for fake implementations and another for actual implementations.
 
Junilu Lacar
Marshal
Posts: 16440
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The problem with instantiating a ReferenceDataHelp instance in the class that's using it is that it violates separation of concerns. Dependency injection separates the concerns of creating a dependency and using a dependency. This allows your designs to be more loosely coupled and more testable. Having the dependency injected makes it easy to inject a fake implementation that you can have more control over during unit testing.

If you are hardcoding the dependency on ReferenceDataHelp in the class that uses it, then you'll have a more difficult time controlling it for unit testing purposes. More difficult but not impossible. The key is to keep the creation of the dependency fairly isolated and easier to override its behavior.

So instead of this:

You'd do this:

Then in the test:

This is the class you can use for testing. The only thing you're replacing is the actual method of getting the ReferenceData, everything else you're exercising in the test comes from the actual RulesEvaluator class.
 
Junilu Lacar
Marshal
Posts: 16440
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Of course if there are multiple ways you are using the ReferenceDataHelp object, you could also do this instead:
 
Junilu Lacar
Marshal
Posts: 16440
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All of the previous approaches are less than ideal though if you have an option to do straight up dependency injection instead.
 
Anand Athinarayanan
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you so much. These are very helpful. The separate JARs are something new to me. so would the build scripts have to be tweaked to have the correct jars on the classpath ?
 
Junilu Lacar
Marshal
Posts: 16440
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, they would but that's probably the least cumbersome aspect of that approach. I personally wouldn't attempt that unless there was absolutely no other way to get testability. The more cumbersome aspect is that you'll have yet another build artifact to deal with and a parallel line of code to keep in synch with production and test code. That's why I'd much rather use dependency injection.

I was simply offering that approach to make the point that there are other ways to achieve better testability besides dependency injection.
 
Anand Athinarayanan
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Understood. Makes sense to make it easy to test. Thank you for your help. Much appreciated.
 
Yeast devil! Back to the oven that baked you! And take this tiny ad too:
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
reply
    Bookmark Topic Watch Topic
  • New Topic