Successfully reported this slideshow.

Anton Minashkin Dagger 2 light

2

Share

Loading in …3
×
1 of 36
1 of 36

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Anton Minashkin Dagger 2 light

  1. 1. Dagger 2. Right way to do Dependency Injections by Anton Minashkin
  2. 2. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = EmployeeDatabase.getInstance() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  3. 3. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = EmployeeDatabase.getInstance() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  4. 4. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = new EmployeeDatabase() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  5. 5. What is DI? In software engineering, dependency injection is a software design pattern that implements inversion of control for software libraries.
  6. 6. What is DI?
  7. 7. Say “Hi!” to DI public class Payroll { ... EmployeeDatabase mEmployeeDatabase; public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = mEmployeeDatabase.getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  8. 8. Say “Hi!” to DI public class Payroll { ... EmployeeDatabase mEmployeeDatabase; public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = mEmployeeDatabase.getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  9. 9. ...but! Was: new Payroll().getAfterTaxPay(employee); Now: new Payroll(EmployeeDatabase.getInstance()) .getAfterTaxPay(employee);
  10. 10. ...but! Was: new Payroll().getAfterTaxPay(employee); Now: new Payroll(EmployeeDatabase.getInstance()) .getAfterTaxPay(employee);
  11. 11. Java! To the rescue! JSR-330
  12. 12. JSR-330 public class Payroll { ... @Inject public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } ... } OR public class Payroll { ... @Inject EmployeeDatabase mEmployeeDatabase; ... }
  13. 13. DI frameworks ● Google Guice ● Spring DI ● Java EE6 CDI ● Dagger ● etc.
  14. 14. DI frameworks ● Google Guice ● Spring DI ● Java EE6 CDI ● Dagger ● etc.
  15. 15. Dagger 2. History Developed by Square Adopted by Google (Dagger 2)
  16. 16. Dagger 2. Main features ● Android friendly ● JSR-330 ● Compile-time DI validation ● Full stack code generation ● User mimic code ● Easy to debug & understand
  17. 17. Dagger 2. API class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.heater = heater; } ... }
  18. 18. Dagger 2. API class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }
  19. 19. Dagger 2. API @Module class DripCoffeeModule { @Provides Heater provideHeater() { return new ElectricHeater(); } @Provides Pump providePump(Thermosiphon pump) { return pump; } }
  20. 20. Dagger 2. API @Component(modules = DripCoffeeModule.class) interface CoffeeShop { CoffeeMaker maker(); }
  21. 21. Dagger 2. API CoffeeShop coffeeShop = DaggerCoffeeShop.builder() .dripCoffeeModule(new DripCoffeeModule()) .build(); ... CoffeeShop coffeeShop = DaggerCoffeeShop.create();
  22. 22. Dagger 2. API public class CoffeeApp { public static void main(String[] args) { CoffeeShop coffeeShop = DaggerCoffeeShop.create(); coffeeShop.maker().brew(); } }
  23. 23. Dagger 2. Scope @Provides @Singleton Heater provideHeater() { return new ElectricHeater(); }
  24. 24. Dagger 2. Lazy class GridingCoffeeMaker { @Inject Lazy<Grinder> lazyGrinder; public void brew() { while (needsGrinding()) { // Grinder created once on first call to .get() and cached. lazyGrinder.get().grind(); } } }
  25. 25. Dagger 2. Provider Injection class BigCoffeeMaker { @Inject Provider<Filter> filterProvider; public void brew(int numberOfPots) { ... for (int p = 0; p < numberOfPots; p++) { maker.addFilter(filterProvider.get()); //new filter every time. maker.addCoffee(...); maker.percolate(); ... } } }
  26. 26. Dagger 2. Qualifiers @Qualifier @Documented @Retention(RUNTIME) public @interface Named { String value() default ""; }
  27. 27. Dagger 2. Qualifiers class ExpensiveCoffeeMaker { @Inject @Named("water") Heater waterHeater; @Inject @Named("hot plate") Heater hotPlateHeater; ... }
  28. 28. Dagger 2. Qualifiers @Provides @Named("hot plate") Heater provideHotPlateHeater() { return new ElectricHeater(70); } @Provides @Named("water") Heater provideWaterHeater() { return new ElectricHeater(93); }
  29. 29. Dagger 2. Compile-time validation @Module class DripCoffeeModule { @Provides Heater provideHeater(Executor executor) { return new CpuHeater(executor); } } ... [ERROR] COMPILATION ERROR : [ERROR] error: java.util.concurrent.Executor cannot be provided without an @Provides-annotated method.
  30. 30. Dagger 2. Generated code @Override public DataManager get() { DataManager provided = module.provideDataManager(authApiProvider.get(), articleApiProvider.get(), commentsApiProvider.get()); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<DataManager> create(DataManagerModule module, Provider<AuthApi> authApiProvider, Provider<ArticleApi> articleApiProvider, Provider<CommentApi> commentApiProvider) { return new DataManagerModule_ProvideDataManagerFactory(module, authApiProvider, articleApiProvider, commentApiProvider); }
  31. 31. Dagger 2. Debugging Here should be example of Guice stacktrace: VERY-VERY-BAD-STACKTRACE And here is Dagger stacktrace: Mmmm… What a lovely stacktrace!
  32. 32. Dagger 2. What should I inject? ● Anything that has constructor parameters ● Anything that is out of local scope ● Infrastructure ● Anything that is shared between >1 objects ● Diferent obj-graphs for diferent flavors
  33. 33. Dagger 2. Where should I inject? public class MyApp extends Application { @Override public void onCreate() { registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { ... @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { inject(activity); } ... }); }
  34. 34. Dagger 2 Example
  35. 35. Dagger 2 Questions?
  36. 36. RTFM! http://google.github.io/dagger/ https://youtu.be/oK_XtfXPkqw anton.minashkin@outlook.com

×