Dagger A fast dependency injector for Android and Java. Thursday, - - PowerPoint PPT Presentation

dagger
SMART_READER_LITE
LIVE PREVIEW

Dagger A fast dependency injector for Android and Java. Thursday, - - PowerPoint PPT Presentation

Jesse Wilson from Square Dagger A fast dependency injector for Android and Java. Thursday, November 8, 12 Introduction Motivation Using Dagger Inside Dagger Wrapping Up Thursday, November 8, 12 Guice Jesse javax.inject Android


slide-1
SLIDE 1

Dagger

Jesse Wilson from Square A fast dependency injector for Android and Java.

Thursday, November 8, 12
slide-2
SLIDE 2

Introduction Motivation Using Dagger Inside Dagger Wrapping Up

Thursday, November 8, 12
slide-3
SLIDE 3

Jesse

  • Guice
  • javax.inject
  • Android Core Libraries
Thursday, November 8, 12
slide-4
SLIDE 4 Thursday, November 8, 12
slide-5
SLIDE 5

We’re Hiring! squareup.com/careers

Thursday, November 8, 12
slide-6
SLIDE 6

Introduction Motivation Using Dagger Inside Dagger Wrapping Up

Thursday, November 8, 12
slide-7
SLIDE 7

Motivation for Dependency Injection

  • Decouple concrete from concrete
  • Uniformity
Thursday, November 8, 12
slide-8
SLIDE 8

Dependency Injection Choices

  • PicoContainer
  • Spring
  • Guice
  • javax.inject
Thursday, November 8, 12
slide-9
SLIDE 9 (cc) creative commons from flickr.com/photos/getbutterfly/6317955134/ Thursday, November 8, 12
slide-10
SLIDE 10 (cc) creative commons from flickr.com/photos/wikidave/2988710537/ Thursday, November 8, 12
slide-11
SLIDE 11

We still love you, Froyo

  • Eager vs. lazy graph construction
  • Reflection vs. codegen
Thursday, November 8, 12
slide-12
SLIDE 12 typicalprogrammer.com/?p=143

“I didn’t really expect anyone to use [git] because it’s so hard to use, but that turns out to be its big appeal. No technology can ever be too arcane or complicated for the black t-shirt crowd.” –Linus Torvalds

Thursday, November 8, 12
slide-13
SLIDE 13

No black t-shirt necessary

Thursday, November 8, 12
slide-14
SLIDE 14 (cc) creative commons from flickr.com/photos/mike_miley/5969110684/ Thursday, November 8, 12
slide-15
SLIDE 15
  • Know everything at

build time.

  • Easy to see how

dependencies are used & satisfied

CoffeeApp CoffeeMaker Pump Heater Thermosiphon Thursday, November 8, 12
slide-16
SLIDE 16

Motivation for Dagger

  • It's like Guice, but with speed

instead of features

  • Simple
  • Predictable
also... Thursday, November 8, 12
slide-17
SLIDE 17

Introduction Motivation Using Dagger Inside Dagger Wrapping Up

Thursday, November 8, 12
slide-18
SLIDE 18

Dagger?

Thursday, November 8, 12
slide-19
SLIDE 19

DAGger.

Thursday, November 8, 12
slide-20
SLIDE 20

Directed Acyclic Graph

DAGger.

Thursday, November 8, 12
slide-21
SLIDE 21 (cc) creative commons from flickr.com/photos/uscpsc/7894303566/ Thursday, November 8, 12
slide-22
SLIDE 22 (cc) creative commons from flickr.com/photos/uscpsc/7894303566/ Thursday, November 8, 12
slide-23
SLIDE 23 (cc) creative commons from flickr.com/photos/uscpsc/7894303566/

coffee maker heater thermosiphon pump

Thursday, November 8, 12
slide-24
SLIDE 24 (cc) creative commons from flickr.com/photos/uscpsc/7894303566/ CoffeeApp CoffeeMaker Pump Heater Thermosiphon Thursday, November 8, 12
slide-25
SLIDE 25

class Thermosiphon implements Pump { private final Heater heater; Thermosiphon(Heater heater) { this.heater = heater; } @Override public void pump() { if (heater.isHot()) { System.out.println("=> => pumping => =>"); } } }

Thursday, November 8, 12
slide-26
SLIDE 26

class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.heater = heater; } ... }

Declare Dependencies

Thursday, November 8, 12
slide-27
SLIDE 27

class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }

Declare Dependencies

Thursday, November 8, 12
slide-28
SLIDE 28

@Module class DripCoffeeModule { @Provides Heater provideHeater() { return new ElectricHeater(); } @Provides Pump providePump(Thermosiphon pump) { return pump; } }

Satisfy Dependencies

Thursday, November 8, 12
slide-29
SLIDE 29

class CoffeeApp { public static void main(String[] args) { ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule()); CoffeeMaker coffeeMaker = objectGraph.get(CoffeeMaker.class); coffeeMaker.brew(); } }

Build the Graph

Thursday, November 8, 12
slide-30
SLIDE 30

Neat features

  • Lazy<T>
  • Module overrides
  • Multibindings
Thursday, November 8, 12
slide-31
SLIDE 31

class GridingCoffeeMaker { @Inject Lazy<Grinder> lazyGrinder; public void brew() { while (needsGrinding()) { // Grinder created once and cached. Grinder grinder = lazyGrinder.get() grinder.grind(); } } }

Lazy<T>

Thursday, November 8, 12
slide-32
SLIDE 32

@Module( includes = DripCoffeeModule.class, entryPoints = CoffeeMakerTest.class,

  • verrides = true

) static class TestModule { @Provides @Singleton Heater provideHeater() { return Mockito.mock(Heater.class); } }

Module Overrides

Thursday, November 8, 12
slide-33
SLIDE 33

@Module class TwitterModule { @Provides(type=SET) SocialApi provideApi() { ... } } @Module class GooglePlusModule { @Provides(type=SET) SocialApi provideApi() { ... } } ... @Inject Set<SocialApi>

Multibindings

Thursday, November 8, 12
slide-34
SLIDE 34

Introduction Motivation Using Dagger Inside Dagger Wrapping Up

Thursday, November 8, 12
slide-35
SLIDE 35

Graphs!

Thursday, November 8, 12
slide-36
SLIDE 36

Creating Graphs

  • Compile time
  • annotation processor
  • Runtime
  • generated code loader
  • reflection
Thursday, November 8, 12
slide-37
SLIDE 37

Using Graphs

  • Injection
  • Validation
  • Graphviz!
Thursday, November 8, 12
slide-38
SLIDE 38

But how?

  • Bindings have names like

“com.squareup.geo.LocationMonitor”

  • Bindings know the names of their

dependencies, like

“com.squareup.otto.Bus”

Thursday, November 8, 12
slide-39
SLIDE 39 final class CoffeeMaker$InjectAdapter extends Binding<CoffeeMaker> { private Binding<Heater> f0; private Binding<Pump> f1; public CoffeeMaker$InjectAdapter() { super("coffee.CoffeeMaker", ...); } public void attach(Linker linker) { f0 = linker.requestBinding("coffee.Heater", coffee.CoffeeMaker.class); f1 = linker.requestBinding("coffee.Pump", coffee.CoffeeMaker.class); } public CoffeeMaker get() { coffee.CoffeeMaker result = new coffee.CoffeeMaker(); injectMembers(result); return result; } public void injectMembers(CoffeeMaker object) {
  • bject.heater = f0.get();
  • bject.pump = f1.get();
} public void getDependencies(Set<Binding<?>> bindings) { bindings.add(f0); bindings.add(f1); } } Thursday, November 8, 12
slide-40
SLIDE 40

Validation

  • Eager at build time
  • Lazy at runtime
Thursday, November 8, 12
slide-41
SLIDE 41

dagger-compiler

(cc) creative commons from flickr.com/photos/discover-central-california/8010906617 Thursday, November 8, 12
slide-42
SLIDE 42

Built into javac Foolishly easy to use. Just put

dagger-compiler on your classpath!

javax.annotation.processing

Thursday, November 8, 12
slide-43
SLIDE 43

It’s a hassle (for us)

  • Coping with prebuilt .jar files
  • Versioning
  • Testing
Thursday, November 8, 12
slide-44
SLIDE 44

... and it’s limited (for you)

  • No private or final field access
  • Incremental builds are imperfect
  • ProGuard
Thursday, November 8, 12
slide-45
SLIDE 45

... but it’s smoking fast! (for your users)

  • Startup time for Square Wallet
  • n one device improved from

~5 seconds to ~2 seconds

Thursday, November 8, 12
slide-46
SLIDE 46

Different Platforms are Different

  • HotSpot
  • Android
  • GWT
Thursday, November 8, 12
slide-47
SLIDE 47

HotSpot: Java on the Server

  • The JVM is fast
  • Code bases are huge
Thursday, November 8, 12
slide-48
SLIDE 48

Android

  • Battery powered
  • Garbage collection causes jank
  • Slow reflection, especially on older

devices

  • Managed lifecycle
Thursday, November 8, 12
slide-49
SLIDE 49

GWT

  • Code size really matters
  • Compiler does full-app
  • ptimizations
  • No reflection.

github.com/tbroyer/sheath

Thursday, November 8, 12
slide-50
SLIDE 50

API Design in the GitHub age

  • Forking makes it easy to stay small

& focused

Thursday, November 8, 12
slide-51
SLIDE 51

public @interface Inject {} public @interface Named { String value() default ""; } public interface Provider { T get(); } public @interface Qualifier {} public @interface Scope {} public @interface Singleton {}

javax.inject

Thursday, November 8, 12
slide-52
SLIDE 52
  • public interface Lazy<T> {
  • T get();
  • }
  • public interface MembersInjector<T> {
  • void injectMembers(T instance);
  • }
  • public final class ObjectGraph {
  • public static ObjectGraph create(Object... modules);
  • public ObjectGraph plus(Object... modules);
  • public void validate();
  • public void injectStatics();
  • public <T> T get(Class type);
  • public <T> T inject(T instance);
  • }
  • public @interface Module {
  • Class[] entryPoints() default { };
  • Class[] staticInjections() default { };
  • Class[] includes() default { };
  • Class addsTo() default Void.class;
  • boolean overrides() default false;
  • boolean complete() default true;
  • }
  • public @interface Provides {
  • enum Type { UNIQUE, SET }
  • Type type() default Type.UNIQUE;
  • }

dagger

Thursday, November 8, 12
slide-53
SLIDE 53

Introduction Motivation Using Dagger Inside Dagger Wrapping Up

Thursday, November 8, 12
slide-54
SLIDE 54
  • Still the best choice for many apps
  • May soon be able to mix & match

with Dagger

Guice

Thursday, November 8, 12
slide-55
SLIDE 55
  • Dagger 0.9 today!
  • Dagger 1.0 in 2012ish
  • Friendly open source.

Dagger

Thursday, November 8, 12
slide-56
SLIDE 56

square.github.com/dagger

Thursday, November 8, 12
slide-57
SLIDE 57

Questions?

squareup.com/careers corner.squareup.com swank.ca jwilson@squareup.com

Thursday, November 8, 12