Di & dagger

  • View
    73

  • Download
    0

Embed Size (px)

Text of Di & dagger

  • (With Dagger2)

    Dependency Injection

  • Hi There!

    Software Developer for three years Medical Research

    eCommerce

    Android Developer at heart and profession

    Software Developer at Gett

  • Game Plan*

    Whats in it for me?

    Dependency Injection Principles

    Dagger2

    *To the best of our ability :)

  • Whats in it for me?

    Testable Code

    If I were to plug this code somewhere else, is it guaranteed to work the same

    way?

    Maintainable Code

    How many what the.. moments am I having while reading this code?

  • Testable And Maintainable Code?

    public class SomeClass {

    private SomeOtherClass someOtherClass;

    public SomeClass() {

    someOtherClass = new SomeOtherClass;

    }

    }

  • Testable And Maintainable Code!

    public class Customer {

    private Breakfast breakfast;

    public Customer(Breakfast breakfast) {

    this.breakfast = breakfast;

    }

    }

  • Game Plan

    Whats in it for me?

    Dependency Injection Principles

    Dagger2

  • Breakfast!

  • Breakfast!

    Breakfast

    Coffee OmeletteBreadJuice Salad

    Water SugarMilk VeggiesSaltEggs Olive OilFruit

  • What is a Dependency?

    A state in which an object uses a function of another object

    Class A is dependent on class B if and only if A needs B in order to function

    Defined by import statements

  • So how do we use dependencies?

  • So how do we use dependencies?

    new statements

    this.breakfast = new Breakfast();

    Singleton objects

    this.breakfast = Breakfast.getInstance();

    Through constructors and methods

    this.breakfast = breakfastParameter;

    Inversion Of Control

  • What is Dependency Injection?

    A technique whereby one object supplies the dependencies of

    another object (wikipedia)

    A technique whereby one object supplies the dependencies of

    another object (wikipedia)

    There are many ways to do it

    We just saw four ways!

    DI acronym

  • Ready for some extremely difficult code?

  • Extremely difficult code ahead!

    // Constructor

    public Customer(Breakfast breakfast) {

    // Save the reference to the dependency as passed in by the creator

    this.mBreakfast = breakfast;

    }

    // Setter Method

    public void setBreakfast(Breakfast breakfast) {

    // Save the reference to the dependency as passed in by the creator

    this.mBreakfast = breakfast;

    }

  • Okay great, can we go now?

  • Just one questionHow should we create our Breakfast object?

  • How do we create a breakfast object?

    // .. Some code above

    Breakfast breakfast = new Breakfast(

    new Coffee(

    // Dependencies go here..

    ), new Juice(

    // Dependencies go here..

    // Some more initializations

    );

    // Give the client their breakfast

  • How do we create a breakfast object?

    // .. Some code above

    Breakfast breakfast = new Breakfast(

    new BlackCoffee(Coffee(

    // Dependencies go here..

    ), new Juice(

    // Dependencies go here..

    // Some more initializations

    );

    // Give the client their breakfast

  • How do we create a breakfast object?

    // .. Some code above

    Breakfast breakfast = new Breakfast(

    new BlackCoffee(Coffee(

    new Sugarless,

    new Skimlesss(new Milk()

    // Dependencies go here..

    ), new Juice(

    // Dependencies go here..

    // Some more initializations

    );

    // Give the client their breakfast

  • Some questions to consider

    What if Breakfast is a supertype of other breakfast types?

    Factories could work

    What if Breakfast is a singleton in the system?

    Sure, but singletons are difficult to test

    Can we share breakfast instances with different clients?

    Kind of, but its difficult to maintain

  • Dependency Injection - A Technique

    A technique whereby one object supplies the dependencies of

    another object (wikipedia)

    Just like breakfast, I could do it myself

    But sometimes I want a restaurant to do it for me

    Because Im lazy

    Because they make it better

    [Insert whatever reason you want here]

    Inversion of control

  • Examples

  • Game Plan*

    Purpose

    Dependency Injection Principles

    Dagger2

    *To the best of our ability :)

  • Why Dagger2?

    Designed for low-end devices

    Generates new code in your application

    No Reflection

  • How Do Restaurants Work?

  • How Does Dagger2 Work?

    Modules Component Clients

  • Module - The Supplier

    Goal

    Provides dependencies

    Providing your dependencies context

  • Modules At A High Level

    A supplier supplies materials

    It declares what it supplies as a contract

    The restaurant can only get what the supplier supplies

    May depend on material it can supply

    May depend on material it cannot supply

  • BreakfastSupplierModule example

    @Module

    public class BreakfastSupplierModule {

    @Provides

    Omelette provideOmelette(Eggs eggs) { // The eggs will be supplied from the method below

    return new ScrambledOmelette();

    }

    @Provides

    Coffee provideCoffee() { // Method name does not matter

    return new BlackCoffee();

    }

    @Provides

    Eggs provideEggs() {

    return new Eggs();

    }

    }

  • Modules - Some FAQ

    Unless stated otherwise

    The module recreates each object it provides

    Read on @Singleton for single-instance

    May depend on other modules dependencies

    May depend on its own dependencies

  • Components - The Restaurants

    Goal

    Bridges between the suppliers and the customers

    Handles the final touches of the basic materials

  • Components At a High Level

    Gathers all of the ingredients from all its suppliers

    Serves a defined set of customers

  • RestaurantComponent example

    @Component(modules = {BreakfastSupplierModule.class})

    public interface RestaurantComponent {

    // injection methods

    void inject(Customer aCustomer);

    }

  • Client Classes

    Use the @Inject annotation to get what they need

    Are supplied through the component

  • @Inject example

    public class Customer {

    @Inject Omelette omelette;

    @Inject Coffee coffee;

    // More code goes here...

    }

  • And Now we Build

  • Component Usage

    The customer depends on the component

    The customer asks the component to serve itself

  • Component Usage - One way

    @Inject Omellete omelette;

    @Inject Coffee coffee;

    public Customer()

    DaggerRestaurantComponent.builder()

    .build().breakfastSupplierModule(new BreakfastSupplierModule)

    .inject(this);

    }

  • Component Usage - Better way

    @Inject Omellete omelette;

    @Inject Coffee coffee;

    public Customer(BreakfastSupplierModule breakfastModule) {

    DaggerRestaurantComponent.builder()

    .build().breakfastSupplierModule(breakfastModule)

    .inject(this);

    }

  • Component Usage - Dagger Master Way

    @Inject Omellete omelette;

    @Inject Coffee coffee;

    public Customer(RestaurantComponent restaurantComponent) {

    restaurantComponent.inject(this);

    }

  • Best Practices

    Dos and Donts

  • Dont @Inject constructorYou dont know where youll find yourself

    Seriously Just dont use @Inject constructor...

  • Law of DemeterDont talk to strangers

  • Dont!

    public class MenuManager {

    private SharedPreferences sharedPreferences;

    public MenuManager(Context context) {

    this.sharedPreferences = context.getSharedPreferences(PREFERENCES_NAME,

    Context.MODE_PRIVATE);

    }

    }

  • Do!

    public class MenuManager {

    private SharedPreferences sharedPreferences;

    public MenuManager(SharedPreferences sharedPreferences) {

    this.sharedPreferences = sharedPreferences;

    }

    }

  • Verdict

    Testing is difficult

    Context can do too much for its own good

    I can just pass the SharedPreferences, right?

  • The client should just reflect its API through its dependencies

  • Constructor InjectionMy dependencies are created before me, and my creation can still be controlled

  • Dont!

    public class Customer {

    // Another Way simply initialize

    public Customer() {

    this.breakfast = new Breakfast();

    }

    }

  • Dont!

    public class Customer {

    // One Way - Inject through component

    @Inject Breakfast breakfast;

    }

  • Do!

    public class Customer {

    private Breakfast breakfast;

    public SomeClient(Breakfast breakfast) {

    mSomeService = someService;

    }

    }

  • Verdict

    Difficult to test

    Client does not reflect its API

    What if Breakfast has dependencies?

  • If we can create the object on our own, well just pass the dependencies through the

    Constructor

  • Setter Method InjectionMy dependencies are created after me, but my creation can still be controlled

  • Dont!

    public class MenuView extends LinearLayout {

    // Another Way

    public Breakfast() {

    breakfast = new Breakfast()

    }

    }

  • Dont!

    public class MenuView extends LinearLayout {

    // One Way