Di & dagger
-
Upload
vitali-pekelis -
Category
Software
-
view
88 -
download
0
Transcript of Di & dagger
![Page 1: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/1.jpg)
(With Dagger2)
Dependency Injection
![Page 2: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/2.jpg)
![Page 3: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/3.jpg)
Hi There!
● Software Developer for three years○ Medical Research
○ eCommerce
● Android Developer at heart and profession
● Software Developer at Gett
![Page 4: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/4.jpg)
Game Plan*
●What’s in it for me?
●Dependency Injection Principles
●Dagger2
*To the best of our ability :)
![Page 5: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/5.jpg)
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?”
![Page 6: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/6.jpg)
Testable And Maintainable Code?
public class SomeClass {
private SomeOtherClass someOtherClass;
public SomeClass() {
someOtherClass = new SomeOtherClass;
}
}
![Page 7: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/7.jpg)
Testable And Maintainable Code!
public class Customer {
private Breakfast breakfast;
public Customer(Breakfast breakfast) {
this.breakfast = breakfast;
}
}
![Page 8: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/8.jpg)
Game Plan
●What’s in it for me?
●Dependency Injection Principles
●Dagger2
![Page 9: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/9.jpg)
Breakfast!
![Page 10: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/10.jpg)
Breakfast!
Breakfast
Coffee OmeletteBreadJuice Salad
Water SugarMilk VeggiesSaltEggs Olive OilFruit
![Page 11: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/11.jpg)
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
![Page 12: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/12.jpg)
So how do we use dependencies?
![Page 13: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/13.jpg)
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
![Page 14: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/14.jpg)
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
![Page 15: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/15.jpg)
Ready for some extremely difficult code?
![Page 16: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/16.jpg)
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;
}
![Page 17: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/17.jpg)
Okay great, can we go now?
![Page 18: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/18.jpg)
Just one questionHow should we create our Breakfast object?
![Page 19: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/19.jpg)
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
![Page 20: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/20.jpg)
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
![Page 21: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/21.jpg)
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
![Page 22: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/22.jpg)
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
![Page 23: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/23.jpg)
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]
● Inversion of control
![Page 24: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/24.jpg)
Examples
![Page 25: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/25.jpg)
Game Plan*
●Purpose
●Dependency Injection Principles
●Dagger2
*To the best of our ability :)
![Page 26: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/26.jpg)
Why Dagger2?
●Designed for low-end devices
●Generates new code in your application
○ No Reflection
![Page 27: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/27.jpg)
How Do Restaurants Work?
![Page 28: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/28.jpg)
How Does Dagger2 Work?
Modules Component Clients
![Page 29: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/29.jpg)
Module - The Supplier
●Goal
○ Provides dependencies
○ Providing your dependencies context
![Page 30: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/30.jpg)
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
![Page 31: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/31.jpg)
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();
}
}
![Page 32: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/32.jpg)
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
![Page 33: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/33.jpg)
Components - The Restaurants
●Goal
○ Bridges between the suppliers and the customers
○ Handles the final touches of the “basic materials”
![Page 34: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/34.jpg)
Components At a High Level
●Gathers all of the ingredients from all its suppliers
●Serves a defined set of customers
![Page 35: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/35.jpg)
RestaurantComponent example
@Component(modules = {BreakfastSupplierModule.class})
public interface RestaurantComponent {
// injection methods
void inject(Customer aCustomer);
}
![Page 36: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/36.jpg)
Client Classes
●Use the @Inject annotation to get what they need
●Are supplied through the component
![Page 37: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/37.jpg)
@Inject example
public class Customer {
@Inject Omelette omelette;
@Inject Coffee coffee;
// More code goes here...
}
![Page 38: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/38.jpg)
And Now we “Build”
![Page 39: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/39.jpg)
Component Usage
●The customer depends on the component
●The customer asks the component to serve itself
![Page 40: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/40.jpg)
Component Usage - One way
@Inject Omellete omelette;
@Inject Coffee coffee;
public Customer()
DaggerRestaurantComponent.builder()
.build().breakfastSupplierModule(new BreakfastSupplierModule)
.inject(this);
}
![Page 41: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/41.jpg)
Component Usage - Better way
@Inject Omellete omelette;
@Inject Coffee coffee;
public Customer(BreakfastSupplierModule breakfastModule) {
DaggerRestaurantComponent.builder()
.build().breakfastSupplierModule(breakfastModule)
.inject(this);
}
![Page 42: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/42.jpg)
Component Usage - Dagger Master Way
@Inject Omellete omelette;
@Inject Coffee coffee;
public Customer(RestaurantComponent restaurantComponent) {
restaurantComponent.inject(this);
}
![Page 43: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/43.jpg)
Best Practices
Dos and Don’ts
![Page 44: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/44.jpg)
Don’t @Inject constructorYou don’t know where you’ll find yourself
Seriously… Just don’t use @Inject constructor...
![Page 45: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/45.jpg)
Law of DemeterDon’t talk to strangers
![Page 46: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/46.jpg)
Don’t!
public class MenuManager {
private SharedPreferences sharedPreferences;
public MenuManager(Context context) {
this.sharedPreferences = context.getSharedPreferences(PREFERENCES_NAME,
Context.MODE_PRIVATE);
}
}
![Page 47: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/47.jpg)
Do!
public class MenuManager {
private SharedPreferences sharedPreferences;
public MenuManager(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
}
}
![Page 48: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/48.jpg)
Verdict
●Testing is difficult
●Context can do too much for its own good
● I can just pass the SharedPreferences, right?
![Page 49: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/49.jpg)
The client should just reflect its API through its dependencies
![Page 50: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/50.jpg)
Constructor InjectionMy dependencies are created before me, and my creation can still be controlled
![Page 51: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/51.jpg)
Don’t!
public class Customer {
// Another Way simply initialize
public Customer() {
this.breakfast = new Breakfast();
}
}
![Page 52: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/52.jpg)
Don’t!
public class Customer {
// One Way - Inject through component
@Inject Breakfast breakfast;
}
![Page 53: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/53.jpg)
Do!
public class Customer {
private Breakfast breakfast;
public SomeClient(Breakfast breakfast) {
mSomeService = someService;
}
}
![Page 54: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/54.jpg)
Verdict
●Difficult to test
●Client does not reflect its API
●What if Breakfast has dependencies?
![Page 55: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/55.jpg)
If we can create the object on our own, we’ll just pass the dependencies through the
Constructor
![Page 56: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/56.jpg)
Setter Method InjectionMy dependencies are created after me, but my creation can still be controlled
![Page 57: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/57.jpg)
Don’t!
public class MenuView extends LinearLayout {
// Another Way
public Breakfast() {
breakfast = new Breakfast()
}
}
![Page 58: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/58.jpg)
Don’t!
public class MenuView extends LinearLayout {
// One Way
@Inject Breakfast breakfast;
}
![Page 59: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/59.jpg)
Kind of works, but not really...
public class MenuView extends LinearLayout {
public MenuView(Context context, Breakfast breakfast) {
this.breakfast = breakfast;
}
}
![Page 60: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/60.jpg)
Do!
public class MenuView extends LinearLayout {
private Breakfast breakfast;
public void setBreakfast(Breakfast breakfast) {
this.breakfast = breakfast;
}
}
![Page 61: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/61.jpg)
Verdict
●Difficult to test
●View does not reflect its API
●What if Breakfast has dependencies?
●Usage may be limited
![Page 62: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/62.jpg)
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
![Page 63: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/63.jpg)
@Inject for Framework ComponentsThe user can’t create me, and can only use me
![Page 64: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/64.jpg)
Don’t!
public class BreakfastActivity extends AppCompatActivity {
private Breakfast breakfast;
public void onCreate(Bundle savedInstanceState) {
this.breakfast = new Breakfast(savedInstanceState);
}
}
![Page 65: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/65.jpg)
Do!
public class BreakfastActivity extends AppCompatActivity {
@Inject Breakfast breakfast;
public SomeClient() {
getActivityComponent().inject(this);
}
}
![Page 66: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/66.jpg)
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)
![Page 67: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/67.jpg)
If the object may only be created by the system, and we may not reference it, we’ll
use dagger’s @Inject feature
![Page 68: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/68.jpg)
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
![Page 69: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/69.jpg)
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();
}
}
![Page 70: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/70.jpg)
BreakfastSupplierModule - Broken Up
@Module
public class CoffeeModule {
@Provides
Omelette provideCoffee() {
return new BlackCoffee();
}
}
![Page 71: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/71.jpg)
RestaurantComponent Result
@Component(modules = {OmeletteModule.class, CoffeeModule.class})
public interface RestaurantComponent {
// injection methods
void inject(Customer aCustomer);
}
![Page 72: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/72.jpg)
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
![Page 73: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/73.jpg)
Thank yous
● https://www.techyourchance.com○ Inspiration, ideas and overall thank yous
![Page 74: Di & dagger](https://reader030.fdocuments.in/reader030/viewer/2022021418/5aabd1b87f8b9aaf528b51b1/html5/thumbnails/74.jpg)
Thank you