SlideShare a Scribd company logo
Dependency Injection
Practice, Practice, Practice A young concert violinist got lost on his way to a performance. He stoped an old man on the corner and asked him how to get to Carnige Hall. The old man looked at the violinist and the violin tucked under his arm, and said: “ Practice, son, Practice ! ” Theory-Practice: a positive feedback system
Why DI?
public class Emailer { private SpellChecker spellChecker; public Emailer() { this.spellChecker = new SpellChecker(); } public void send(String text) { .. } } How about testing?  public class MockSpellChecker extends SpellChecker { private boolean didCheckSpelling = false; public boolean checkSpelling(String text) { didCheckSpelling = true; return true; } public boolean verifyDidCheckSpelling(){  return didCheckSpelling;  } } And what about the Open-Closed Principle?
The Factory Pattern public class EmailerFactory { /* The Factory is explicit about the object it produces...*/ public Emailer newItalianEmailer() { return new Emailer(new ItalianSpellChecker()); } } Emailer service = new EmailerFactory().newItalianEmailer(); @Test public void testEmailer() { MockSpellChecker spellChecker = ... Emailer emailer = new Emailer( spellChecker ); emailer.send("Fatte DI in ufficio!"); assert ...; } Client Factory Service
What about the client? public class EmailerClient { private Emailer emailer = new EmailerFactory().newItalianEmailer(); public void sendEmail() { emailer.send(createMessage()); } } public class EmailerFactory { private static Emailer instance;  // did you see the problem here? public Emailer newEmailer() { if (null == instance) return new Emailer(..); return instance; } static void  set (Emailer mock) { instance = mock; } } @Test public void testEmailClient() { MockEmailer mock = new MockEmailer(); EmailerFactory.set(mock); new EmailClient().sendEmail(); assert mock.correctlySent(); } @Test public void testEmailClient() { MockEmailer mock = new MockEmailer(); EmailerFactory.set(mock); try { new EmailClient().sendEmail(); assert mock.correctlySent(); } finally { EmailerFactory.set(null); } }
The Service Locator Pattern Is a generalization of the Factory Emailer emailer = (Emailer) new ServiceLocator().get("ItalianEmailer"); Emailer emailer = (Emailer) new ServiceLocator().get(" JapaneseEmailerWithPhoneAndEmail "); (as a Factory) suffers from same problems:  testability and shared state Do you remember the ServiceManager anti-pattern?
DI Hollywood Principle Behaviorally focused Modular Separation of concerns, Demeter's law, Decoupling TESTABLE
My main(String... args) is better than yours... public class EmailerClient { private final Emailer emailer; public EmailerClient(Emailer emailer){ this.emailer = emailer; } public void sendEmail() { emailer.send(createMessage()); } ... } public static void main(String... args) throws Exception { // by hand (new ApplicationFactory(args).create()).start();  } public static void main(String... args) throws Exception { // using Guice Injector injector = Guice.createInjector(new ApplicationModule(args)); (injector.getInstance(Application.class)).start(); }
What have changed? Client code (EmailerClient) doesn't invoke the injector (separation of concerns) The  root-object  is explicit  (Application.class) The injector obtains instances within current execution context (scoping)
How to identify a dependency Dependency:  Contract Variants public interface SpellChecker { boolean check(String text); } class ItalianSpellChecker implements SpellChecker { public boolean check(String text) {/* check italian */ ...} } class EnglishSpellChecker implements SpellChecker { public boolean check(String text) {/* check english */ ...} } (new Emailer( new EnglishSpellChecker() )).send(“Hello”); (new Emailer( new ItalianSpellChecker() )).send(“Ciao”); KEY: Unique Arbitrary Explicit
String Keys  (Spring) Pros Unique Arbitrary Explicit Cons Error-prone No compile-time safe You “can't” use Vim but IntelliJ Idea  Must be carefully choosen Examples: <beans ...> <bean id=”spelling.english” class=”it.xpug.milan.service.text. EnglishSpellChecker ”/> <bean id=”spelling.italian” class=”it.xpug.milan.service.text.ItalianSpellChecker”/> </beans>
Identifying by Type Pros Compile-time safe Right direction Cons Not unique Not arbitrary Explicitness? Inflexible Examples: SpellChecker.class identifies EnglishSpellChecker or ItalianSpellChecker Emailer.class identifies itself
Combinatorial Keys (Guice) Key = [contract, variant] Key1: [Emailer.class, “english”] Key2: [Emailer.class, “italian”] Key3:  [Emailer.class, “English”] Or better: Key1: [Emailer.class, English.class] Key2: [Emailer.class, Italian.class] @Retention( RUNTIME ) @Target( { PARAMETER } ) public @interface English { ... } public class Emailer{ private final  SpellChecker spellChecker; @Inject public SpellCheckerClient( @English  SpellChecker spellChecker) { this. spellChecker = spellChecker; } } public class SpellingModule extends    AbstractModule { @Override protected void configure() {   bind(SpellChecker.class) . annotatedWith(English.class) . to(EnglishSpellChecker.class); }
Injection Idioms Setter injection public class Emailer { private SpellChecker spellChecker; public void  setSpellChecker (SpellChecker spellChecker) { this. spellChecker = spellChecker; } } <beans  ...xmlns:p=&quot;http://www.springframework.org/schema/p&quot;...> <bean id=&quot;spelling.english&quot; class=&quot;package.EnglishSpellChecker&quot;/> <bean id=”emailer” class =”package.Emailer” p:spellChecker=&quot;spelling.english&quot;/> </beans> Interface Injection (Deprecated) Method Decoration (via AOP)
Constructor Injection public class Emailer { private final SpellChecker spellChecker; // potentially immutable public Emailer(SpellChecker spellChecker){ this.spellChecker = spellChecker; // freezing the object graph } } <beans ...> <bean id=”emailer” class =”package.Emailer”> <constructor-arg> <bean class=&quot;package.EnglishSpellChecker&quot;/> </constructor-arg> </bean> </beans>
Constructor vs Setter  Injection Constructor Clear contract Immutability support or temporal encapsulation Ready for use/ Object validity No need for noisy setters Setter Esplicitness (type indipendent) Doesn't  suffers from the pyramid/telescoping problem Doesn't suffers from the circular dependency and some in-construction problems
GOF's Creational Patterns Abstract Factory Factory Method Builder Prototype Singleton
The Reinjection Problem When a long-lived dependent needs a short-lived dependencies public class Granny { private Apple apple; public Granny(Apple apple) { this.apple = apple; } public void eat() { apple.consume(); apple.consume(); } } /** Provides specific object and scoped intances of those  objects. */ public interface Provider<T> { T get(); } public class AppleProvider implements Provider<Apple>{ public Apple get(){ return new Apple(); } } public class Granny { private Provider<Apple> appleProvider; public Granny(Provider<Apple> ap) { this.appleProvider = ap; } public void eat() { appleProvider.get().consume(); appleProvider.get().consume(); } }
Or using the builder pattern.. public class Granny { private AppleBuilder builder; public Granny(AppleBuilder b) { this.builder = b; } public void eat() { builder.buildRedApple().consume(); builder.buildGreenApple().consume(); } } public class AppleBuilder { public Apple buildRedApple() { return new RedApple(); } public Apple buildGreenApple() { return new GreenApple(); } } and its Jochua's version...
The Contextual Injection Problem public class NewsletterManager { private final List<Recipient> recipients; private final AssistedProvider<Deliverer, Newsletter> deliverer; public NewsletterManager(List<Recipient> rs,AssistedProvider<Deliverer,Newsletter> dp){ this.recipients = rs; this.deliverer = dp; } public void send(Newsletter letter) { for (Recipient recipient : recipients) { Deliverer d = deliverer.get(letter); d.deliverTo(recipient); } } } public interface AssistedProvider<T, C> { T get(C context); } public class DelivererProvider implements AssistedProvider<Deliverer,Newsletter> { public Deliverer get(Newsletter letter) { return new Deliverer(letter); } }
Scope Is a fixed duration of time or method calls in which an object exists A context under which a given key refers to the same instance Mostly used: Singleton and No-Scope Interesting scopes: Transaction, Web, Cache, Thread, Grid, Custom...
Why Scope? Applies the Hollywood Principle to the  state  of the objects The injector manages the latent state of your  objects The injector ensures that the services get new instance of dependencies as needed Implicity separates state by context Reduces the necessity for state-aware application logic (separation of concerns – infrastructure/business logic)
Defining a Custom Scope Guice public interface Scope { <T> Provider<T> scope(Key<T> key, Provider<T> unscoped); } public class TransactionScope implements Scope { private final ThreadLocal<Map<Key<?>, Object>> instances  = new ThreadLocal<Map<Key<?>, Object>>(); public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped) { return new Provider<T>() { public T get() { Map<Key<?>, Object> map = instances.get(); if (null == map) { throw new OutOfScopeException(&quot;no transaction was active&quot;); } if (!map.containsKey(key)) { map.put(key, unscoped.get()) } return (T) map.get(key); } }; } // called by the transaction framework public void beginScope() { instances.set(new HashMap<Key<?>, Object>()); } public void endScope() {instances.remove();}}
Defining a Custom Scope (Cont.) Spring public interface Scope { Object get(String key, ObjectFactory unscopedProvider); Object remove(String key); String getConversationId();  // scope identity, ex. SessionId // lifecycle method void registerDestructionCallback(String key, Runnable destructionCallback); } <beans ...> <bean  class=&quot;org.springframework.beans.factory.config.CustomScopeConfigurer&quot;> <property name=&quot;scopes&quot;> <map> <entry key=&quot;transaction&quot;> <bean class=&quot;my.custom.TransactionScope&quot;/> </entry> </map> </property> </bean> ... </beans>
public class TransactionScope implements Scope { private final ThreadLocal<Map<String, Object>> instances = new ThreadLocal<Map<String, Object>>(); public Object get(String key, ObjectFactory unscoped) { Map<String, Object> map = instances.get(); //check out of scope if (null == map) throw new IllegalStateException(&quot;no transaction is active&quot;); if (!map.containsKey(key)) { map.put(key, unscoped.getObject()); } return map.get(key); } public void beginScope() { instances.set(new HashMap<String, Object>()); } public void endScope() { instances.remove(); } public Object remove(String key) { // check out of scope ... return instances.get().remove(key); } public String getConversationId() { // check out of scope ... return instances.get().toString(); } public void registerDestructionCallback(String key, Runnable destructionCallback) { ... } }
public static final Scope SINGLETON = new Scope() { public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) { return new Provider<T>() { /* * The lazily initialized singleton instance. Once set, this will either have type T or will * be equal to NULL. */ private volatile Object instance; // DCL on a volatile is safe as of Java 5, which we obviously require. @SuppressWarnings(&quot;DoubleCheckedLocking&quot;) public T get() { if (instance == null) { /* * Use a pretty coarse lock. We don't want to run into deadlocks * when two threads try to load circularly-dependent objects. * Maybe one of these days we will identify independent graphs of * objects and offer to load them in parallel. */ synchronized (InjectorBuilder.class) { if (instance == null) { T nullableInstance = creator.get(); instance = (nullableInstance != null) ? nullableInstance : NULL; } } } Object localInstance = instance; // This is safe because instance has type T or is equal to NULL @SuppressWarnings(&quot;unchecked&quot;) T returnedInstance = (localInstance != NULL) ? (T) localInstance : null; return returnedInstance; } public String toString() { return String.format(&quot;%s[%s]&quot;, creator, SINGLETON); } }; } }; Did you see how it helps to the modularity?
Related stuff Lifecycle Postprocessors AOP
Lifecycle in DI Closely related to the scope but of different semantic Related to the nature of the object Is about state transitions / event driven Moslty used: init and destroy Can be constructed over other specific lifecycles (ex. servlet or db connections) PostProcessors – register to a particular lifecycle
AOP in DI Attention: much power means much responsability! Unit Testing somewhat is fading, much more like  Integration Test Aop Alliance (Guice, Spring) AspectJ (Spring)
DI + AOP = DDD? Eric Evans - 2008 Although DDD can be done with any paradigm that allows abstraction and expression of model concepts, in practice it has almost always been OOP. So, OOP has been a foundation of the practice of DDD. More recently, DI has become a very widespread technique and, when used well, has helped practitioners of DDD to improve their designs. Most importantly, in my view, DI helps in the &quot;isolation&quot; of the domain. The potential of AOP is just beginning to be realized. It seems that it has potential to declutter the domain layer. This contributes to the clear expression of the model concepts, and perhaps to isolation. But, unlike the first two (OOP and DI), it isn't a tried and true part of a &quot;foundation&quot; yet. These form a foundation of a current best practice architecture that supports DDD .
DI for Java SE JSR 330  (299-Web Beans?) @Inject  - Identifies injectable constructors, methods, and fields @Qualifier  - Identifies qualifier annotations @Scope  - Identifies scope annotations @Named  - String-based qualifier @Singleton  - Identifies a type that the injector only instantiates once
Some DI Frameworks Java APACHE AVALON SPRING FRAMEWORK PICOCONTAINER AND NANOCONTAINER APACHE HIVEMIND GOOGLE GUICE BUTTERFLY DI DSL Ruby COPLAND
References Dependency Injection - Dhanji R. Prasanna*  http://www.manning.com/prasanna/ Misko Hevery* Blog http://misko.hevery.com/ *  Many thanks to both of you from the slide's author

More Related Content

PDF
Living With Legacy Code
Rowan Merewood
 
PDF
Sony C#/.NET component set analysis
PVS-Studio
 
PDF
The First C# Project Analyzed
PVS-Studio
 
KEY
How To Test Everything
noelrap
 
PDF
It's complicated, but it doesn't have to be: a Dagger journey
Thiago “Fred” Porciúncula
 
PDF
Checking Clang 11 with PVS-Studio
Andrey Karpov
 
PPTX
Mutation Testing - Ruby Edition
Chris Sinjakli
 
PPT
EasyMock for Java
Deepak Singhvi
 
Living With Legacy Code
Rowan Merewood
 
Sony C#/.NET component set analysis
PVS-Studio
 
The First C# Project Analyzed
PVS-Studio
 
How To Test Everything
noelrap
 
It's complicated, but it doesn't have to be: a Dagger journey
Thiago “Fred” Porciúncula
 
Checking Clang 11 with PVS-Studio
Andrey Karpov
 
Mutation Testing - Ruby Edition
Chris Sinjakli
 
EasyMock for Java
Deepak Singhvi
 

What's hot (20)

PDF
Unit testing with PHPUnit - there's life outside of TDD
Paweł Michalik
 
PDF
Analyzing the Blender project with PVS-Studio
PVS-Studio
 
PDF
Brief analysis of Media Portal 2 bugs
PVS-Studio
 
PPT
Software Engineering
Robbie Clutton
 
PDF
JavaScript Refactoring
Krzysztof Szafranek
 
PDF
Working Effectively with Legacy Code
slicklash
 
PDF
Example First / A Sane Test-Driven Approach to Programming
Jonathan Acker
 
PPTX
Rspec 101
Jason Noble
 
PDF
Why Your Test Suite Sucks - PHPCon PL 2015
CiaranMcNulty
 
PPTX
Exception
Sandeep Chawla
 
PDF
Looking for Bugs in MonoDevelop
PVS-Studio
 
PDF
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
PDF
Source code of WPF samples by Microsoft was checked
PVS-Studio
 
PDF
C++ boot camp part 1/2
Jesse Talavera-Greenberg
 
PPTX
Post Sharp Talk
willmation
 
PDF
Unit testing PHP apps with PHPUnit
Michelangelo van Dam
 
PDF
Testdriven Development using JUnit and EasyMock
schlebu
 
PDF
Introduction to Unit Testing with PHPUnit
Michelangelo van Dam
 
PDF
Still Comparing "this" Pointer to Null?
Andrey Karpov
 
PDF
Virtual events in C#: something went wrong
PVS-Studio
 
Unit testing with PHPUnit - there's life outside of TDD
Paweł Michalik
 
Analyzing the Blender project with PVS-Studio
PVS-Studio
 
Brief analysis of Media Portal 2 bugs
PVS-Studio
 
Software Engineering
Robbie Clutton
 
JavaScript Refactoring
Krzysztof Szafranek
 
Working Effectively with Legacy Code
slicklash
 
Example First / A Sane Test-Driven Approach to Programming
Jonathan Acker
 
Rspec 101
Jason Noble
 
Why Your Test Suite Sucks - PHPCon PL 2015
CiaranMcNulty
 
Exception
Sandeep Chawla
 
Looking for Bugs in MonoDevelop
PVS-Studio
 
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
Source code of WPF samples by Microsoft was checked
PVS-Studio
 
C++ boot camp part 1/2
Jesse Talavera-Greenberg
 
Post Sharp Talk
willmation
 
Unit testing PHP apps with PHPUnit
Michelangelo van Dam
 
Testdriven Development using JUnit and EasyMock
schlebu
 
Introduction to Unit Testing with PHPUnit
Michelangelo van Dam
 
Still Comparing "this" Pointer to Null?
Andrey Karpov
 
Virtual events in C#: something went wrong
PVS-Studio
 
Ad

Similar to Dependency Injection (20)

ODP
Bring the fun back to java
ciklum_ods
 
PPTX
Navigating the xDD Alphabet Soup
Dror Helper
 
PPTX
Back-2-Basics: .NET Coding Standards For The Real World (2011)
David McCarter
 
PDF
Tdd iPhone For Dummies
Giordano Scalzo
 
PDF
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
FalafelSoftware
 
PDF
Breaking Dependencies to Allow Unit Testing
Steven Smith
 
PDF
Ejb3 Dan Hinojosa
Dan Hinojosa
 
PPT
Stopping the Rot - Putting Legacy C++ Under Test
Seb Rose
 
PPT
J Unit
guest333f37c3
 
PDF
Dependency injection
Eugenio Lentini
 
PDF
Getting Started With Testing
Giovanni Scerra ☃
 
PPTX
Legacy Dependency Kata v2.0
William Munn
 
PPTX
Guice gin
Robert Cooper
 
PDF
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Naresha K
 
PDF
Unit testing - A&BP CC
JWORKS powered by Ordina
 
PPTX
Sapphire Gimlets
Robert Cooper
 
PDF
谷歌 Scott-lessons learned in testability
drewz lin
 
PDF
Java 例外處理壞味道與重構技術
teddysoft
 
PDF
Design for Testability
Stefano Dalla Palma
 
PDF
Keep your Wicket application in production
Martijn Dashorst
 
Bring the fun back to java
ciklum_ods
 
Navigating the xDD Alphabet Soup
Dror Helper
 
Back-2-Basics: .NET Coding Standards For The Real World (2011)
David McCarter
 
Tdd iPhone For Dummies
Giordano Scalzo
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Steven Smith
 
Ejb3 Dan Hinojosa
Dan Hinojosa
 
Stopping the Rot - Putting Legacy C++ Under Test
Seb Rose
 
Dependency injection
Eugenio Lentini
 
Getting Started With Testing
Giovanni Scerra ☃
 
Legacy Dependency Kata v2.0
William Munn
 
Guice gin
Robert Cooper
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Naresha K
 
Unit testing - A&BP CC
JWORKS powered by Ordina
 
Sapphire Gimlets
Robert Cooper
 
谷歌 Scott-lessons learned in testability
drewz lin
 
Java 例外處理壞味道與重構技術
teddysoft
 
Design for Testability
Stefano Dalla Palma
 
Keep your Wicket application in production
Martijn Dashorst
 
Ad

Recently uploaded (20)

PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PDF
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
PDF
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
PDF
Doc9.....................................
SofiaCollazos
 
PPTX
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
PDF
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
OFFOFFBOX™ – A New Era for African Film | Startup Presentation
ambaicciwalkerbrian
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PDF
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
PPTX
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
Doc9.....................................
SofiaCollazos
 
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
OFFOFFBOX™ – A New Era for African Film | Startup Presentation
ambaicciwalkerbrian
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 

Dependency Injection

  • 2. Practice, Practice, Practice A young concert violinist got lost on his way to a performance. He stoped an old man on the corner and asked him how to get to Carnige Hall. The old man looked at the violinist and the violin tucked under his arm, and said: “ Practice, son, Practice ! ” Theory-Practice: a positive feedback system
  • 4. public class Emailer { private SpellChecker spellChecker; public Emailer() { this.spellChecker = new SpellChecker(); } public void send(String text) { .. } } How about testing? public class MockSpellChecker extends SpellChecker { private boolean didCheckSpelling = false; public boolean checkSpelling(String text) { didCheckSpelling = true; return true; } public boolean verifyDidCheckSpelling(){ return didCheckSpelling; } } And what about the Open-Closed Principle?
  • 5. The Factory Pattern public class EmailerFactory { /* The Factory is explicit about the object it produces...*/ public Emailer newItalianEmailer() { return new Emailer(new ItalianSpellChecker()); } } Emailer service = new EmailerFactory().newItalianEmailer(); @Test public void testEmailer() { MockSpellChecker spellChecker = ... Emailer emailer = new Emailer( spellChecker ); emailer.send(&quot;Fatte DI in ufficio!&quot;); assert ...; } Client Factory Service
  • 6. What about the client? public class EmailerClient { private Emailer emailer = new EmailerFactory().newItalianEmailer(); public void sendEmail() { emailer.send(createMessage()); } } public class EmailerFactory { private static Emailer instance; // did you see the problem here? public Emailer newEmailer() { if (null == instance) return new Emailer(..); return instance; } static void set (Emailer mock) { instance = mock; } } @Test public void testEmailClient() { MockEmailer mock = new MockEmailer(); EmailerFactory.set(mock); new EmailClient().sendEmail(); assert mock.correctlySent(); } @Test public void testEmailClient() { MockEmailer mock = new MockEmailer(); EmailerFactory.set(mock); try { new EmailClient().sendEmail(); assert mock.correctlySent(); } finally { EmailerFactory.set(null); } }
  • 7. The Service Locator Pattern Is a generalization of the Factory Emailer emailer = (Emailer) new ServiceLocator().get(&quot;ItalianEmailer&quot;); Emailer emailer = (Emailer) new ServiceLocator().get(&quot; JapaneseEmailerWithPhoneAndEmail &quot;); (as a Factory) suffers from same problems: testability and shared state Do you remember the ServiceManager anti-pattern?
  • 8. DI Hollywood Principle Behaviorally focused Modular Separation of concerns, Demeter's law, Decoupling TESTABLE
  • 9. My main(String... args) is better than yours... public class EmailerClient { private final Emailer emailer; public EmailerClient(Emailer emailer){ this.emailer = emailer; } public void sendEmail() { emailer.send(createMessage()); } ... } public static void main(String... args) throws Exception { // by hand (new ApplicationFactory(args).create()).start(); } public static void main(String... args) throws Exception { // using Guice Injector injector = Guice.createInjector(new ApplicationModule(args)); (injector.getInstance(Application.class)).start(); }
  • 10. What have changed? Client code (EmailerClient) doesn't invoke the injector (separation of concerns) The root-object is explicit (Application.class) The injector obtains instances within current execution context (scoping)
  • 11. How to identify a dependency Dependency: Contract Variants public interface SpellChecker { boolean check(String text); } class ItalianSpellChecker implements SpellChecker { public boolean check(String text) {/* check italian */ ...} } class EnglishSpellChecker implements SpellChecker { public boolean check(String text) {/* check english */ ...} } (new Emailer( new EnglishSpellChecker() )).send(“Hello”); (new Emailer( new ItalianSpellChecker() )).send(“Ciao”); KEY: Unique Arbitrary Explicit
  • 12. String Keys (Spring) Pros Unique Arbitrary Explicit Cons Error-prone No compile-time safe You “can't” use Vim but IntelliJ Idea Must be carefully choosen Examples: <beans ...> <bean id=”spelling.english” class=”it.xpug.milan.service.text. EnglishSpellChecker ”/> <bean id=”spelling.italian” class=”it.xpug.milan.service.text.ItalianSpellChecker”/> </beans>
  • 13. Identifying by Type Pros Compile-time safe Right direction Cons Not unique Not arbitrary Explicitness? Inflexible Examples: SpellChecker.class identifies EnglishSpellChecker or ItalianSpellChecker Emailer.class identifies itself
  • 14. Combinatorial Keys (Guice) Key = [contract, variant] Key1: [Emailer.class, “english”] Key2: [Emailer.class, “italian”] Key3: [Emailer.class, “English”] Or better: Key1: [Emailer.class, English.class] Key2: [Emailer.class, Italian.class] @Retention( RUNTIME ) @Target( { PARAMETER } ) public @interface English { ... } public class Emailer{ private final SpellChecker spellChecker; @Inject public SpellCheckerClient( @English SpellChecker spellChecker) { this. spellChecker = spellChecker; } } public class SpellingModule extends AbstractModule { @Override protected void configure() { bind(SpellChecker.class) . annotatedWith(English.class) . to(EnglishSpellChecker.class); }
  • 15. Injection Idioms Setter injection public class Emailer { private SpellChecker spellChecker; public void setSpellChecker (SpellChecker spellChecker) { this. spellChecker = spellChecker; } } <beans ...xmlns:p=&quot;http://www.springframework.org/schema/p&quot;...> <bean id=&quot;spelling.english&quot; class=&quot;package.EnglishSpellChecker&quot;/> <bean id=”emailer” class =”package.Emailer” p:spellChecker=&quot;spelling.english&quot;/> </beans> Interface Injection (Deprecated) Method Decoration (via AOP)
  • 16. Constructor Injection public class Emailer { private final SpellChecker spellChecker; // potentially immutable public Emailer(SpellChecker spellChecker){ this.spellChecker = spellChecker; // freezing the object graph } } <beans ...> <bean id=”emailer” class =”package.Emailer”> <constructor-arg> <bean class=&quot;package.EnglishSpellChecker&quot;/> </constructor-arg> </bean> </beans>
  • 17. Constructor vs Setter Injection Constructor Clear contract Immutability support or temporal encapsulation Ready for use/ Object validity No need for noisy setters Setter Esplicitness (type indipendent) Doesn't suffers from the pyramid/telescoping problem Doesn't suffers from the circular dependency and some in-construction problems
  • 18. GOF's Creational Patterns Abstract Factory Factory Method Builder Prototype Singleton
  • 19. The Reinjection Problem When a long-lived dependent needs a short-lived dependencies public class Granny { private Apple apple; public Granny(Apple apple) { this.apple = apple; } public void eat() { apple.consume(); apple.consume(); } } /** Provides specific object and scoped intances of those objects. */ public interface Provider<T> { T get(); } public class AppleProvider implements Provider<Apple>{ public Apple get(){ return new Apple(); } } public class Granny { private Provider<Apple> appleProvider; public Granny(Provider<Apple> ap) { this.appleProvider = ap; } public void eat() { appleProvider.get().consume(); appleProvider.get().consume(); } }
  • 20. Or using the builder pattern.. public class Granny { private AppleBuilder builder; public Granny(AppleBuilder b) { this.builder = b; } public void eat() { builder.buildRedApple().consume(); builder.buildGreenApple().consume(); } } public class AppleBuilder { public Apple buildRedApple() { return new RedApple(); } public Apple buildGreenApple() { return new GreenApple(); } } and its Jochua's version...
  • 21. The Contextual Injection Problem public class NewsletterManager { private final List<Recipient> recipients; private final AssistedProvider<Deliverer, Newsletter> deliverer; public NewsletterManager(List<Recipient> rs,AssistedProvider<Deliverer,Newsletter> dp){ this.recipients = rs; this.deliverer = dp; } public void send(Newsletter letter) { for (Recipient recipient : recipients) { Deliverer d = deliverer.get(letter); d.deliverTo(recipient); } } } public interface AssistedProvider<T, C> { T get(C context); } public class DelivererProvider implements AssistedProvider<Deliverer,Newsletter> { public Deliverer get(Newsletter letter) { return new Deliverer(letter); } }
  • 22. Scope Is a fixed duration of time or method calls in which an object exists A context under which a given key refers to the same instance Mostly used: Singleton and No-Scope Interesting scopes: Transaction, Web, Cache, Thread, Grid, Custom...
  • 23. Why Scope? Applies the Hollywood Principle to the state of the objects The injector manages the latent state of your objects The injector ensures that the services get new instance of dependencies as needed Implicity separates state by context Reduces the necessity for state-aware application logic (separation of concerns – infrastructure/business logic)
  • 24. Defining a Custom Scope Guice public interface Scope { <T> Provider<T> scope(Key<T> key, Provider<T> unscoped); } public class TransactionScope implements Scope { private final ThreadLocal<Map<Key<?>, Object>> instances = new ThreadLocal<Map<Key<?>, Object>>(); public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped) { return new Provider<T>() { public T get() { Map<Key<?>, Object> map = instances.get(); if (null == map) { throw new OutOfScopeException(&quot;no transaction was active&quot;); } if (!map.containsKey(key)) { map.put(key, unscoped.get()) } return (T) map.get(key); } }; } // called by the transaction framework public void beginScope() { instances.set(new HashMap<Key<?>, Object>()); } public void endScope() {instances.remove();}}
  • 25. Defining a Custom Scope (Cont.) Spring public interface Scope { Object get(String key, ObjectFactory unscopedProvider); Object remove(String key); String getConversationId(); // scope identity, ex. SessionId // lifecycle method void registerDestructionCallback(String key, Runnable destructionCallback); } <beans ...> <bean class=&quot;org.springframework.beans.factory.config.CustomScopeConfigurer&quot;> <property name=&quot;scopes&quot;> <map> <entry key=&quot;transaction&quot;> <bean class=&quot;my.custom.TransactionScope&quot;/> </entry> </map> </property> </bean> ... </beans>
  • 26. public class TransactionScope implements Scope { private final ThreadLocal<Map<String, Object>> instances = new ThreadLocal<Map<String, Object>>(); public Object get(String key, ObjectFactory unscoped) { Map<String, Object> map = instances.get(); //check out of scope if (null == map) throw new IllegalStateException(&quot;no transaction is active&quot;); if (!map.containsKey(key)) { map.put(key, unscoped.getObject()); } return map.get(key); } public void beginScope() { instances.set(new HashMap<String, Object>()); } public void endScope() { instances.remove(); } public Object remove(String key) { // check out of scope ... return instances.get().remove(key); } public String getConversationId() { // check out of scope ... return instances.get().toString(); } public void registerDestructionCallback(String key, Runnable destructionCallback) { ... } }
  • 27. public static final Scope SINGLETON = new Scope() { public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) { return new Provider<T>() { /* * The lazily initialized singleton instance. Once set, this will either have type T or will * be equal to NULL. */ private volatile Object instance; // DCL on a volatile is safe as of Java 5, which we obviously require. @SuppressWarnings(&quot;DoubleCheckedLocking&quot;) public T get() { if (instance == null) { /* * Use a pretty coarse lock. We don't want to run into deadlocks * when two threads try to load circularly-dependent objects. * Maybe one of these days we will identify independent graphs of * objects and offer to load them in parallel. */ synchronized (InjectorBuilder.class) { if (instance == null) { T nullableInstance = creator.get(); instance = (nullableInstance != null) ? nullableInstance : NULL; } } } Object localInstance = instance; // This is safe because instance has type T or is equal to NULL @SuppressWarnings(&quot;unchecked&quot;) T returnedInstance = (localInstance != NULL) ? (T) localInstance : null; return returnedInstance; } public String toString() { return String.format(&quot;%s[%s]&quot;, creator, SINGLETON); } }; } }; Did you see how it helps to the modularity?
  • 28. Related stuff Lifecycle Postprocessors AOP
  • 29. Lifecycle in DI Closely related to the scope but of different semantic Related to the nature of the object Is about state transitions / event driven Moslty used: init and destroy Can be constructed over other specific lifecycles (ex. servlet or db connections) PostProcessors – register to a particular lifecycle
  • 30. AOP in DI Attention: much power means much responsability! Unit Testing somewhat is fading, much more like Integration Test Aop Alliance (Guice, Spring) AspectJ (Spring)
  • 31. DI + AOP = DDD? Eric Evans - 2008 Although DDD can be done with any paradigm that allows abstraction and expression of model concepts, in practice it has almost always been OOP. So, OOP has been a foundation of the practice of DDD. More recently, DI has become a very widespread technique and, when used well, has helped practitioners of DDD to improve their designs. Most importantly, in my view, DI helps in the &quot;isolation&quot; of the domain. The potential of AOP is just beginning to be realized. It seems that it has potential to declutter the domain layer. This contributes to the clear expression of the model concepts, and perhaps to isolation. But, unlike the first two (OOP and DI), it isn't a tried and true part of a &quot;foundation&quot; yet. These form a foundation of a current best practice architecture that supports DDD .
  • 32. DI for Java SE JSR 330 (299-Web Beans?) @Inject - Identifies injectable constructors, methods, and fields @Qualifier - Identifies qualifier annotations @Scope - Identifies scope annotations @Named - String-based qualifier @Singleton - Identifies a type that the injector only instantiates once
  • 33. Some DI Frameworks Java APACHE AVALON SPRING FRAMEWORK PICOCONTAINER AND NANOCONTAINER APACHE HIVEMIND GOOGLE GUICE BUTTERFLY DI DSL Ruby COPLAND
  • 34. References Dependency Injection - Dhanji R. Prasanna* http://www.manning.com/prasanna/ Misko Hevery* Blog http://misko.hevery.com/ * Many thanks to both of you from the slide's author