3. Hi There!
● Software Developer for three years
○ Medical Research
○ eCommerce
● Android Developer at heart and profession
● Software Developer at Gett
4. Game Plan*
●What’s in it for me?
●Dependency Injection Principles
●Dagger2
*To the best of our ability :)
5. What’s 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?”
6. Testable And Maintainable Code?
public class SomeClass {
private SomeOtherClass someOtherClass;
public SomeClass() {
someOtherClass = new SomeOtherClass;
}
}
7. Testable And Maintainable Code!
public class Customer {
private Breakfast breakfast;
public Customer(Breakfast breakfast) {
this.breakfast = breakfast;
}
}
11. 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
13. 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
14. 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
16. 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;
}
19. 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
20. 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
21. 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
22. 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 it’s difficult to maintain
23. 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 I’m lazy
○ Because they make it better
○ [Insert whatever reason you want here]
29. Module - The Supplier
●Goal
○ Provides dependencies
○ Providing your dependencies context
30. 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
31. 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();
}
}
32. Modules - Some FAQ
●Unless stated otherwise
○ The module recreates each object it provides
○ Read on @Singleton for single-instance
●May depend on other module’s dependencies
●May depend on its own dependencies
33. Components - The Restaurants
●Goal
○ Bridges between the suppliers and the customers
○ Handles the final touches of the “basic materials”
34. Components At a High Level
●Gathers all of the ingredients from all its suppliers
●Serves a defined set of customers
59. Kind of works, but not really...
public class MenuView extends LinearLayout {
public MenuView(Context context, Breakfast breakfast) {
this.breakfast = breakfast;
}
}
60. Do!
public class MenuView extends LinearLayout {
private Breakfast breakfast;
public void setBreakfast(Breakfast breakfast) {
this.breakfast = breakfast;
}
}
62. If the object may be created by the system,
and not us, but we have access to it through
a pointer, we’ll use setter methods to inject
dependencies
64. Don’t!
public class BreakfastActivity extends AppCompatActivity {
private Breakfast breakfast;
public void onCreate(Bundle savedInstanceState) {
this.breakfast = new Breakfast(savedInstanceState);
}
}
65. Do!
public class BreakfastActivity extends AppCompatActivity {
@Inject Breakfast breakfast;
public SomeClient() {
getActivityComponent().inject(this);
}
}
66. Verdict
●System components are only interactable through callbacks
○ We cannot hold references to them, or create them
●Use @Inject to declare their needed dependencies
●Use statically created components to inject them
○ Testability comes through modules
○ Testability comes through extension (TestableObject <- Object)
67. If the object may only be created by the
system, and we may not reference it, we’ll
use dagger’s @Inject feature
68. Other Tips
●Look at the generated code
○ It’s code that is added to your application
●Use separate @Modules for each feature
○ Modules are classes that can be constructed
○ Provide clarity and customization
69. BreakfastSupplierModule - Broken Up
@Module
public class OmeletteModule {
@Provides
Omelette provideOmelette(Eggs eggs) { // The eggs will be supplied from
the method below
return new ScrambledOmelette();
}
@Provides
Eggs provideEggs() {
return new Eggs();
}
}
70. BreakfastSupplierModule - Broken Up
@Module
public class CoffeeModule {
@Provides
Omelette provideCoffee() {
return new BlackCoffee();
}
}
72. Other Tips
●Look at the generated code
○ It’s code that is added to your application
●Use separate @Modules for each feature● Read on Dagger2’s many (many) features
● Kotlin users beware
The following is a list of High-Level Concepts in computer science that led to the postulation of Dependency Injection pattern
These are guidelines that can actually turn into work ethics.
These are still guidelines
Talk about Breakfast metaphor (“Let’s make breakfast”)
First you need to create coffee. To do so you need a machine, water, a capsul and milk. Ok great
Let’s make eggs. You need a pan, eggs, and maybe salt and pepper. Almost there
Let’s make pancakes. You need milk, eggs, batter, and sugar.
Let’s make orange juice. For it you just need oranges and sugar.
Lastly, let’s cut some veggies.
That’s dependency injection at its finest
Talk about Breakfast metaphor (“Let’s make breakfast”)
First you need to create coffee. To do so you need a machine, water, a capsul and milk. Ok great
Let’s make eggs. You need a pan, eggs, and maybe salt and pepper. Almost there
Let’s make pancakes. You need milk, eggs, batter, and sugar.
Let’s make orange juice. For it you just need oranges and sugar.
Lastly, let’s cut some veggies.
That’s dependency injection at its finest
dependency injection is a technique whereby one object supplies the dependencies of another object
There are tons more
Note - there are some languages and frameworks that do not need dependency injection frameworks. We use Java, so naturally we need it. (Think about why)
High level description
High level description
High level description
High level description
The names of the methods again don’t matter
The target is declared as the parameter of the inject method
The modules are declared in the @Component annotation
Base classes do not count - we need concrete implementations
The example shows an activity, but this can be done in any class really.
Note the Injector class section - we will talk about this in the next slide
I would urge you to take these following tips and tricks with a grain of salt, but from my experience this is what helped me organize my code the best
Client Reflects its api
We don’t care what DI Frameworks we use