Découverte du reactive programming : ReactiveX
Cela fait un moment que je cherche à en apprendre un peu plus sur la programmation réactive et tout particulièrement ReactiveX. J'ai trouvé un peu de temps pour ça et ce que j'ai appris m'a bien plu.
Qu'est ce que ReactiveX ?
Pour commencer voyons quelques patterns intéressants.
Le pattern Observer
C'est un design pattern assez vieux et très connu. Il a été très utilisé dans des langages comme Java, C#.NET, etc; notamment grâce à des framework qui l'ont pleinement utilisé.
Il permet de gérer, en gros, des événements. Le principe est le suivant.
J'ai des objets "observables" et des objets "observateurs". Lorsqu'ils ont effectué une certaine action, qu'il y a un changement d'état, ou plus simplement que quelque chose s'est passé dans un objet observable, cet objet observable va notifier ses observateurs du changement.
Ils vont donc lancer / appeler les observateurs au moment le plus opportun.
Le pattern Iterator
Là aussi : c'est un design pattern assez connu et plutôt classique. Vous l'avez forcément déjà utilisé même sans vous en rendre compte.
Ce pattern permet d'accéder simplement aux éléments d'un objet "agrégateur" sans exposer son fonctionnement. Il est très souvent implémenté par défaut dans les langages de programmation.
Si vous avez pensé aux tableaux comme une implémentation de ce design pattern, vous n'avez pas faux. Un tableau de string
est bien un objet qui agrège plusieurs string
. On peut itérer sur le tableau.
Le tableau est un type natif d'agrégateur mais vous n'êtes clairement pas limité à ça. Vous pouvez créer vos propres agrégateurs Iterable
. D'ailleurs les structures itératives (for
, for...of
, for...in
, etc), dans la plupart des langages, ne bouclent pas sur les tableaux, mais bien sur les Iterable
, qu'ils soient des tableaux ou pas. Les tableaux n'étant que des objets implémentant le contrat Iterable
.
Le functional programming
La programmation peut-elle se libérer du style de von Neumann ? : un style fonctionnel et son algèbre des programmes — John Backus
La programmation fonctionnelle, comme le laisse penser cette citation, est très inspirée des mathématiques. C'est une façon de programmer très ancienne mais qui revient un peu à la mode.
J'en ai déjà un peu parlé dans de précédents articles. C'est une façon de programmer que j'affectionne beaucoup car elle permet de réduire les effets de bord.
Je vous expose le principe : une fonction prend des paramètres en entrée et retourne un résultat.
f(x) = x + 2 // math
(x) => x + 2 // javascript
En programmation fonctionnelle, une fonction ne doit rien faire d'autre. C'est ce qu'on appelle aussi des pure functions lorsqu’on l'utilise dans un langage non fonctionnel.
Vous ne voyez pas la différence avec une fonction normale ? Une pure function ne modifie pas les variables qui lui sont passé en paramètre, elle ne lance pas de traitement en taches de fond, elle ne modifie pas d'objet. Il ne doit y avoir aucun effet de bord. Une pure function ne fait que ce qu'on lui demande, rien d'autre.
x => {
console.log(x)
return x + 2
}
Cette fonction n'est pas une pure function.
ReactiveX
ReactiveX est une API qui se présente comme étant "une combinaison des bonnes idées du pattern Observer, du pattern Iterator et de la programmation fonctionnelle".
Chose intéressante, ReactiveX n'est qu'une API. Elle possède par contre des implémentations dans beaucoup de langage connus et très utilisés.
Je vous mets ceux qui m'intéressent mais n'hésitez pas à regarder dans la doc pour savoir si votre langage préféré possède aussi une implémentation officielle de ReactiveX.
Pour ceux qui se demandent où est la programmation réactive (reactive programming) dans cet article mis à part le titre : elle est dans le pattern Observer. La programmation réactive à été inventé pour pallier certaines faiblesses du pattern Observer
.
Ce dernier étant sûrement plus connu et servant de base au précédent, les développeurs ont peut-être jugé préférable de mentionner "the Observer pattern" sur leur site plutôt que "the reactive programming".
Quel est le principe de ReactiveX ?
ReactiveX veut que l'on utilise certains types d'objet comme s'il s'agissait d'Iterable
qui tiennent compte du temps.
C'est peut-être un peu flou dit comme cela mais réfléchissons : si nous pouvons itérer sur une suite de valeur de même type, pourquoi ne pas itérer sur une suite d'événements ? Ce sont aussi des valeurs de même type.
Le seule déférence est la variable temps. Nous ne savons pas quand un événement va être déclenché — ou en d'autre terme, quand un événement va être ajouté à la suite de notre itérable — d'où l'intérêt que notre itérable soit aussi un observable.
Voilà le principe de ReactiveX. Il veut nous permettre d'itérer sur une suite de valeur non-nécessairement synchrone.
Comment s'utilise ReactiveX ?
Après tout ce que l'on vient de dire, je pense que vous avez une petite idée, même vague, de ceux à quoi va ressembler le code.
Si l'on reprend le tableau de base en JavaScript, quelle action itérative allons-nous pouvoir lui appliquer ? Il y en a énormément, mais les principales sont :
tableau
.map(x => x) // modification
.filter(x => true) // filtre
Ces méthodes sont purement fonctionnelles. Le résultat est bien une version modifiée de tableau
mais tableau
n'a pas été modifié par les deux méthodes. Elle retourne un nouvel objet Array
qui respecte les conditions que nous lui passons en prenant pour base tableau
.
Restons donc sur ce type de méthode, mais itérons sur des événements.
const src = Observable.fromEvent(document, 'click')
src
.map(e => e.target.id)
.filter(id => id % 2 === 0)
src.subscribe(val => console.log(val))
On ajoute un observer
à l'événement click
du document. On ne tient compte que des clicks
sur des éléments dont l'id
est pair. Et on affiche.
Ce code n'affiche l'id de l'élément cliqué que si celui-ci est pair.
Conclusion
Vous voyez la puissance de ce code ?
On utilise les mêmes méthodes que pour un tableau, elles ont le même but que celles d’un tableau, leur fonctionnement ne changent pas. On l'a fait aussi simplement que pour un tableau.
Sauf que nous ne traitions pas réellement un tableau, mais belle est bien un événement ! La constante temps est prise en compte.
J’espère que la programmation réactive est un peu plus claire pour vous et que cette introduction vous aura plu.