Dagger 2
Back to basics
@JeremMartinez
1
jeremie-martinez.com
Slide 2
Slide 2 text
Inversion
of Control
“Don’t call us, we’ll call you…”
2
Slide 3
Slide 3 text
Injection de dépendances
JSR-330
Bob Lee
Créateur de Guice
Rod Johnson
Créateur de Spring
3
Slide 4
Slide 4 text
Pourquoi ?
4
Single Responsibility principle
Meilleur découpage
Facilement testable
Meilleur maintenabilité
Qualité de code
Slide 5
Slide 5 text
Un peu
d’Historique
“Once upon a time…”
5
Slide 6
Slide 6 text
Problèmes
6
Slide 7
Slide 7 text
Problèmes
BOILERPLATE
7
du code
Slide 8
Slide 8 text
Problèmes
LENT
à l’initialisation et à l’injection
8
Slide 9
Slide 9 text
Problèmes
LOURD
en mémoire et dans l’APK
9
Slide 10
Slide 10 text
Problèmes
FAIL
au runtime
10
Slide 11
Slide 11 text
Besoins
Analyse statique Pas d’introspection
Fail fast
Aucun impact
11
Slide 12
Slide 12 text
Dagger
by Square
12
Slide 13
Slide 13 text
Dagger 1
Créé en 2012 par Jesse Wilson (Guice)
Encadré par Bob Lee (Guice, JSR330, Guava, CTO Square)
Ouvert en mai 2013
Dernière version en Juillet 2014 (1.2.2)
13
Slide 14
Slide 14 text
Bilan
Rapide et facile
JSR330 Compatible
Utilisable sur Android
Annotation Processing
Ouvert à la communauté Java
Introspection sur les classes
Pas totalement au compile time
Analyse pas totalement statique
Proguard
14
Slide 15
Slide 15 text
Dagger 2
by Google
15
Slide 16
Slide 16 text
Dagger 2
Repris par la Java Core Librairies Team
Assisté par Square
Release en avril 2015
Résout les problématiques restantes de la version 1
16
Slide 17
Slide 17 text
API
17
Slide 18
Slide 18 text
API
Fournir les dépendances : @Provides et @Module
Demander des dépendances : @Inject
Lier les modules et les injections : @Component
Implémenter le pattern singleton : @Singleton
18
Slide 19
Slide 19 text
3 formes d’injection
19
Slide 20
Slide 20 text
3 formes d’injection
Par
constructeur
20
Slide 21
Slide 21 text
Par constructeur
public class ApiManager {
private final Api api;
@Inject
public ApiManager(Api api) {
this.api = api;
}
…
}
21
Slide 22
Slide 22 text
3 formes d’injection
Par
constructeur
Par field
22
Slide 23
Slide 23 text
Par field
public class ApiManager {
@Inject Api api;
…
}
23
Slide 24
Slide 24 text
3 formes d’injection
Par setter
Par
constructeur
Par field
24
Slide 25
Slide 25 text
Par field
public class ApiManager {
private Api api;
@Inject
public void setApi(Api api) { … }
…
}
25
Slide 26
Slide 26 text
Par field
public class ApiManager {
private Api api;
@Inject
public void setApi(Api api) { … }
…
}
Not supported
26
Scope
“(sous-)Graphe local à durée de vie limitée”
Par exemple :
• Singleton
• PerActivity
•PerUser
• PerRequest
38
Slide 39
Slide 39 text
Scope - API
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UserScope{}
Ne pas oublier d’annoter le composant !
39
Slide 40
Slide 40 text
Scope - Conclusion
Clarté du graphe
Mémoire
Meilleure modélisation
40
Slide 41
Slide 41 text
Lazy
@Inject Lazy lazyApi;
ApiManager api = lazyApi.get();
Déplace l’initialisation de l’objet à sa première utilisation
41
Slide 42
Slide 42 text
Named
Injection par chaine de caractères
Un seul qualifier par dépendance
@Inject @Named("userPrefs") SharedPreferences userPrefs;
@Inject @Named("appPrefs") SharedPreferences appPrefs;
@Provides @Named("userPrefs") public SharedPreferences providesUserPrefs()
@Provides @Named("appPrefs") public SharedPreferences providesAppPrefs()
42
Slide 43
Slide 43 text
Tests
“Tester c’est douter…”
43
Slide 44
Slide 44 text
Tests - Dagger
INUTILE
“Si ça compile, ça marche !”
44
Slide 45
Slide 45 text
Tests - Unitaires
public class ApiManager {
private final EventBus bus;
private final Api api;
@Inject
public ApiManager(EventBus bus, Api api) { … }
…
}
45
Slide 46
Slide 46 text
Tests - Unitaires
@RunWith(MockitoJUnitRunner.class)
public class ApiManagerTest {
@Mock EventBus bus;
@Mock Api api;
@InjectMocks ApiManager apiManager;
@Test
public should_call_backend() { … }
…
}
46
Slide 47
Slide 47 text
Tests - Fonctionnels
Pas de bonne solution
47
Slide 48
Slide 48 text
Tests - Fonctionnels
Build variant sur l’Android Gradle Plugin
Mock des modules
Dupliquer les configurations
48