3. Concepts - Définition
«… la programmation réactive est un
paradigme de programmation visant à
conserver une cohérence d'ensemble en
propageant les modifications d'une source
réactive (modification d'une variable, entrée
utilisateur, etc.) aux éléments dépendants de
cette source…»
4.
5. Concepts - Définition
Programmation Réactive
==
programmation avec des flux de données
asynchrones
Réactif
• flux de données
• propagation des changements
Fonctionnel
• décompositions fonctionnelles
• pas d’effets de bord
6. Concepts - Flux de données asynchrone
• Séquence d’événements
• Ordonnés dans le temps
• Non concurents
• 0 à N événements
• Flux fini/infini/vide
10. Besoins - résumé
• Les besoins des applications croient plus
vite que les évolutions matérielles
• Il est temps de repenser l’architecture
logicielle et les techniques de
programmation
11. Besoins - résumé
• Les besoins des applications croient plus
vite que les évolutions matérielles
• Il est temps de repenser l’architecture
logicielle et les techniques de
programmation
12. Liste des personnes de sexe féminin
Push vs Pull
public List<Personne> getSexeFeminin (List<Personne> personnes) {
List<Personne> sexeFeminin = new ArrayList<>();
for(Personne personne: personnes){
if(personne.isFromSexe(Sexe.FEMININ)){
sexeFeminin.add(personne);
}
}
return sexeFeminin;
}
13. Liste des personnes de sexe féminin
Push vs Pull
public List<Personne> getSexeFeminin(List<Personne> personnes) {
return personnes.stream()
.filter(personne -> personne.isFromSexe(Sexe.FEMININ))
.collect(Collectors.toList());
}
14. Liste des personnes de sexe féminin
Push vs Pull
public Observable<Personne> getSexeFeminin (List<Personne> personnes){
return Observable.from(personnes)
.filter(personne-> personne.isFromSexe(Sexe.FEMININ));
}
15. Push vs Pull
Iterable – Iterator
Observable – Observer
Evénement Iterable (Pull) Observable(Push)
Obtenir une valeur T next(); onNext(T);
Remontées des
erreurs
throws Exception(); onError(Throwable);
Complete !hasNext(); onCompleted();
16. Asynchronisme - Future
Bien faire du code asynchrone ?
Future
Se composent mal
Peuvent bloquer (get())
Valeurs scalaires
Gestion des erreurs complexe
17. Asynchronisme - Callback
Bien faire du code asynchrone ?
Callback
Simple
Pas de blocage
Ne se composent pas
Difficilement lisible après 1 niveau (callback hell)
21. //just prend en paramètre un à n objet à emettre
Observable<String> justObs = Observable.just("un","deux","trois");
//from prend en paramètre une instance d'Iterable, un Future ou un
tableau et émet ses éléments
Observable<BigDecimal> fromObs = Observable.from(
Arrays.asList(BigDecimal.ONE, BigDecimal.TEN,BigDecimal.ZERO)
);
//intervall génère une valeur depuis 0, à chaque intervalle spécifé
Observable<Long> intervalObs = Observable.interval(100,10,
TimeUnit.MILLISECONDS);
RxJava - Observable
2 manière d’instancier un observable:
• Via les constructeurs statiques:
22. RxJava - Observable
• via la méthode create, en implémentant l’interface
OnSubscribe:
Observable<String> prenomsObservable = Observable.create(new
Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
try{
for(String prenom : prenoms){
subscriber.onNext(prenom);
}
subscriber.onCompleted();
}catch(Exception ex){
subscriber.onError(ex.getCause());
}
}
});
24. RxJava - Observer
public interface Observer<T> {
void onCompleted();
void onError(Throwable throwable);
void onNext(T next);
}
Contrat RX
onNext : chaque fois qu’un événement est émis
onError : appelé quand une exception survient
onCompleted : fin du flux
25. RxJava - Subscription
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
• Interface permettant de gérer la souscription
• Observable.subscribe() retourne une Subscription
• Représente la lien entre Observable et Observer
26. RxJava - Premier Observable
Observable<String> firstObservable = Observable.create(new
Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber){
subscriber.onNext("Hello");
subscriber.onNext("World");
subscriber.onCompleted();
}
});
27. RxJava - Premier Subscriber
Subscriber<String> firstSubscriber = new Subscriber<String>() {
@Override
public void onNext(String s){
System.out.println("Next: " + s);
}
@Override
public void onCompleted(){
System.out.println("Complete!");
}
@Override
public void onError(Throwable throwable){
System.out.println(throwable.getCause().getMessage();
}
34. RxJava - Penser en terme de flux
Prénoms des personnes de sexes féminins en
majuscule
Observable<User> usersObservable = Observable.from(personnes);
usersObservable
.filter(personne -> {
return personne.isFromSexe(Sexe.FEMININ);
})
.map(personne -> {
return personne.prenom().toUpperCase();
})
.subscribe(value->{
System.out.println(value);
});
35. filter (x –> x.isSexeFrom(Sexe.FEMININ))
map (x –> x.prenom.toUpperCase)
subscribe
Observable.from(personnes)
onNext onNext
onNext
onNext
onNext onNext
onNext
onNext
Completed
Completed
Completed
RxJava - Penser en terme de flux
36. RxJava - Penser en terme de flux, filtre
Observable<User> usersObservable = Observable.from(personnes);
usersObservable
.filter(personne -> {
return personne.isFromSexe(Sexe.FEMININ);
})
.map(personne -> {
return personne.prenom().toUpperCase();
})
.first()
.subscribe(value->{
System.out.println(value);
});
Premier prénom des personnes de sexes féminins
en majuscule
37. first()
filter (x –> x.isSexeFrom(Sexe.FEMININ))
map (x –> x.prenom.toUpperCase)
subscribe
Observable.from(personnes)
onCompleted
onNext onNext
onNext
onNext
onNext
RxJava - Penser en terme de flux, filtre
38. filter (x –> x.isSexeFrom(Sexe.FEMININ))
map (x –> x.prenom.toUpperCase)
subscribe
Observable.from(personnes)
onNext onNext
onNext
onNext
onNext onNext
onNext
onError
RxJava - Penser en terme de flux, erreurs
39. RxJava - Gestion des erreurs
Principes de bases
• Aucune exception levé hors de l’Observable
• CompositeException
• Encapsule plusieurs exception
• OnErrorNotImplementedException
• si onError() pas implémenté
• OnErrorFailedException
• observer.onError() soulève une exception
43. Multithreading - Schedulers
Schedulers Description
Schedulers.computation() Pour calcul long. NThread = NCpu
Schedulers.io() Pool de thread interne. Pour gestion I/O
Schedulers.from(executor) Utilisation d’un Executor
Schedulers.newThread() Un thread pour chaque unité de travail
• Fourni une abstraction pour la gestion de la concurrence
• Fourni différentes stratégies (Thread pools, Event Loops,
Handler, etc…)
• Sert à contrôler l’exécution des traitements
• Associé aux opérateurs subscribeOn et observeOn
44. Multithreading - subscribeOn()
• Indique à l’Observable source sur quel Thread émettre les
événements
• L’ordre d’apparition dans le pipeline n’a aucune importance
• Ou sont émit les événements
48. Multithreading - observeOn()
• Indique aux l’opérateur situé
juste après sur quel Thread
déporter leurs traitements
• Ou sont consommées
les événements
58. Backpressure – reactive pull
• Via une implémentation de l’interface Producer, et de la méthode
request(long n)
• Permet le contrôle de l’émission de l’Observable
• L’Observable doit supporter la backpressure
.subscribe(new Subscriber<Integer>() {
@Override
public void onStart() {
request(1);
}
@Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
request(1);
}
…
59. RxJava - Debugg et tests
Debugg
Méthodes doOnXXX, à effet de bords
• doOnNext
• doOnError
• doOnCompleted
• …