2000 J2EE, Java 1.3 Service Locators 2003 Spring 2007 Guice 2010 JSR 330 2011 RoboGuice 2013 Dagger 2015 Dagger 2 2017 Dagger Android • It started with the new keyword: new Player(….) Nothing says “implementation” more than the new keyword flickr.com/photos/139228535@N05/40102368982
2000 J2EE, Java 1.3 Service Locators 2003 Spring 2007 Guice 2010 JSR 330 2011 RoboGuice 2013 Dagger 2015 Dagger 2 2017 Dagger Android • The Dawn of Dependency Injection • Idea: register the objects and let them handle the creation • Started with xml configuration • With JDK 1.5 came annotation support @AutoWired flickr.com/photos/139228535@N05/40102368982
2000 J2EE, Java 1.3 Service Locators 2003 Spring 2007 Guice 2010 JSR 330 2011 RoboGuice 2013 Dagger 2015 Dagger 2 2017 Dagger Android • RoboGuice started by community • Reflection based Google: don‘t use it flickr.com/photos/139228535@N05/40102368982
2000 J2EE, Java 1.3 Service Locators 2003 Spring 2007 Guice 2010 JSR 330 2011 RoboGuice 2013 Dagger 2015 Dagger 2 2017 Dagger Android • Dagger1 by Square • „similar“ to Guice • Pro: moved from Reflection to compile time • Contra: Graph composition still at runtime, Ugly genereated code flickr.com/photos/139228535@N05/40102368982
is handy: class HomeViewModel @Inject constructor(val resources: Resources) • Violates separations of concerns • Violates clean architecture : DI should stay in outermost layer • Providers are the cleaner solution anyway (part of JSR330)
is handy: class HomeViewModel @Inject constructor(val resources: Resources) • Violates separations of concerns • Violates clean architecture : DI should stay in outermost layer • Providers are the cleaner solution anyway (part of JSR330)
is handy: class HomeViewModel @Inject constructor(val resources: Resources) • Violates separations of concerns • Violates clean architecture : DI should stay in outermost layer • Providers are the cleaner solution anyway (part of JSR330)
is handy: class HomeViewModel @Inject constructor(val resources: Resources) • Violates separations of concerns • Violates clean architecture : DI should stay in outermost layer • Providers are the cleaner solution anyway (part of JSR330)
provided • With service locator: the class asks for it • With injection there is no explicit request • With a Service Locator every user has a dependency to the locator
locator that forces requests be public API • moves validation to compile-time • and lookup is done by code generation • For Service Locators: • Dependencies are no longer part of the API contract. https://twitter.com/JakeWharton/status/908423738244427776
that it doesn't automatically means that it's a Service Locator. • It becomes a Service Locator if used incorrectly: when application code (as opposed to infrastructure code) actively queries a service … then it has become a Service Locator. • Service Locator is ultimately not identified by the mechanics of its API, but by the role it plays. http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/ http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern/
that it doesn't automatically means that it's a Service Locator. • It becomes a Service Locator if used incorrectly: when application code (as opposed to infrastructure code) actively queries a service … then it has become a Service Locator. • Service Locator is ultimately not identified by the mechanics of its API, but by the role it plays. http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/ http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern/
that it doesn't automatically means that it's a Service Locator. • It becomes a Service Locator if used incorrectly: when application code (as opposed to infrastructure code) actively queries a service … then it has become a Service Locator. • Service Locator is ultimately not identified by the mechanics of its API, but by the role it plays. http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/ http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern/
locator that forces requests be public API • moves validation to compile-time • and lookup is done by code generation • For Service Locators: • Dependencies are no longer part of the API contract. https://twitter.com/JakeWharton/status/908423738244427776
locator that forces requests be public API • moves validation to compile-time • and lookup is done by code generation • For Service Locators: • Dependencies are no longer part of the API contract. https://twitter.com/JakeWharton/status/908423738244427776
locator that forces requests be public API • For Service Locators: • Dependencies are no longer part of the API contract. https://twitter.com/JakeWharton/status/908423738244427776
an API that any client should consume • violates SOLID and encapsulation. http://blog.ploeh.dk/2014/05/15/service-locator-violates-solid/ http://blog.ploeh.dk/2015/10/26/service-locator-violates-encapsulation/
is more pure … It is however more cumbersome, and does not provide a lot of features. • retrieval is easier and feature full, but it requires the class to know about Kodein. • In the end, it boils down to that question: Do you need this class to be Kodein independant? http://kodein.org/Kodein-DI/?5.0/getting-started#_injection_vs_retrieval
{ class Deps( val ds: DataSource, val ctrl: controller) val deps by lazy { (applicationContext as MyApplication) .creator.myActivity() } val ds by lazy { deps.ds } val ctrl by lazy { deps.ctrl }
…scales poorly. • A service locator has some overhead in creating it, inserting the bindings, and then doing the lookups. • A dependency injector has a lot of fixed overhead in setting up an injector hierarchy (components in Dagger 2) and all the modules to provide bindings. https://www.reddit.com/r/androiddev/comments/8ch4cg/dagger2_vs_koin_for_dependency_injection/
app with hundreds of bindings and hundreds of injected types with a deep graph of types then you're better off with a proper injector that generates the code that you otherwise manually write worth Koin. https://www.reddit.com/r/androiddev/comments/8ch4cg/dagger2_vs_koin_for_dependency_injection/ only true when using @ constructor without auto wiring, DI container become pointless Manual constructor registration makes it harder to refactor (Mark Seemann)
it to manage the nulls. The language? Or the programmer? • Defects are the fault of programmers. It is programmers who create defects – not languages. • And what is it that programmers are supposed to do to prevent defects? • TEST! flickr.com/photos/steve-maw/4543646311
it to manage the nulls. The language? Or the programmer? • Defects are the fault of programmers. It is programmers who create defects – not languages. • And what is it that programmers are supposed to do to prevent defects? • TEST! https://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html
plant at Chernobyl catch fire, melt down, destroy a small city, and leave a large area uninhabitable? https://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html So don’t depend on safeties to prevent catastrophes They overrode all the safeties. “
DI in your project • Replace all @inject with manual binding calls will be painful • Kodein helps with reflection based javax.inject implementation flickr.com/photos/anca_bejinaru/5234037866/
DI in your project • Replace all @inject with manual binding calls will be painful • Kodein helps with reflection based javax.inject implementation (keeps your project running) flickr.com/photos/anca_bejinaru/5234037866/
• You can not have same class in multiple scope definition • Passing arguments still possible via map in inject() • General issue with lazy: can not be reset! Be careful with leaks