programming in RxSwift and RxCocoa

Dans cet article, nous allons tenter de répondre à des questions telles que :
Qu’est-ce que la programmation réactive ? Qu’est-ce que la programmation réactive fonctionnelle ? Quels avantages pouvons-nous tirer de l’utilisation de Rx dans nos applications et par où commencer pour intégrer Rx dans votre application.

Qu’est-ce que la programmation réactive ?

Probablement, dans chaque article sur la programmation réactive, vous trouverez une référence et un lien vers le Reactive Manifesto. Dans ce document, vous pouvez trouver les affirmations principales concernant les avantages des applications réactives, mais il ne vous donne aucune idée de la manière de les atteindre.

En fait, le Reactive Manifesto n’est qu’une liste des principaux piliers dont votre application réactive doit tenir compte. Spécifiquement, tels que : Responsive, Resilient, Elastic et Message Driven.

Si nous essayons d’exprimer l’idée entière en une seule phrase, nous pouvons obtenir quelque chose comme ceci :
La programmation réactive nous donne la capacité de créer des applications hautement stables et réactives qui peuvent être facilement modifiées ou étendues selon une approche pilotée par les messages. Pour intégrer ces avantages dans votre application, vous pouvez utiliser la programmation réactive. Alors, qu’est-ce que la programmation réactive ?

La programmation réactive est une approche basée sur les principes des flux de données asynchrones et des données immuables. Elle repose sur des concepts de base tels que les Observables, les Observers et les Schedulers. Les deux premiers sont une sorte de réalisation du modèle Observer, éprouvé par le temps. Et les Schedulers aident à la programmation asynchrone et à la gestion des threads.

Par exemple, si vous vous abonnez à une chaîne YouTube, vous recevrez des notifications de nouvelles vidéos ou de diffusions en direct, et vous pourrez les consulter si vous le souhaitez. Il en va de même pour votre projet : vous pouvez vous abonner à un événement et réagir en fonction de la logique de votre application. Les Schedulers interviennent par exemple lorsque vous émettez un événement dans un thread d’arrière-plan et que vous devez y réagir dans le thread principal.

Programmation réactive fonctionnelle

Presque toutes les bibliothèques Rx modernes utilisent les principes de base de la programmation fonctionnelle. Comme vous le savez peut-être, en programmation fonctionnelle, vous manipulez des fonctions, tout comme vous manipulez d’autres types de données comme les entiers ou les chaînes de caractères, et toutes ces valeurs sont immuables.

En programmation fonctionnelle, vous avez toujours affaire à des données immuables, ce qui vous permet de ne pas vous soucier de la concurrence et des états de données actuels, vous offrant ainsi de plus grands avantages à l’utilisation d’une architecture multi-threads asynchrone. De plus, comme la programmation fonctionnelle offre un comportement prévisible, il est beaucoup plus facile de couvrir toute votre logique avec des tests unitaires. Cela peut potentiellement vous donner un produit plus stable.

La FRP utilise le meilleur de la programmation réactive et fonctionnelle. En programmation traditionnelle, nous utilisons également des flux d’événements pour recevoir les activités de l’utilisateur, comme un clic sur un bouton, un changement d’orientation de l’appareil, et autres. En FRP, les variables, les entrées utilisateur, les réponses du serveur, les paramètres des modèles et les modèles eux-mêmes peuvent être représentés comme un flux. Cela élève le niveau d’abstraction, vous permettant ainsi de manipuler les flux au lieu des objets ou des fonctions.

La substance principale de la FRP est l’Observable, qui dispose d’une large gamme d’opérateurs avec lesquels vous implémentez la logique métier de votre application. Les principales catégories de ces opérateurs sont : Transformer les Observables, Filtrer les Observables, Combiner les Observables, et autres. La liste complète et leurs descriptions se trouvent ici.

Cela peut sembler assez difficile à comprendre. Heureusement, pour mieux comprendre la logique de la programmation réactive, nous pouvons utiliser des diagrammes en marbre comme celui-ci :

Vous pouvez trouver de tels diagrammes pour différents opérateurs qui illustrent leur fonctionnement ici.

Programmation réactive fonctionnelle avec Swift

Alors, comment obtenir ces résultats pour votre application ? Pour appliquer Rx à votre projet particulier, vous pouvez utiliser l’une des bibliothèques Rx, dont la liste se trouve ici.

Par exemple, utilisons RxSwift et essayons quelques opérateurs de base.

Commençons par l’opérateur “filter”.
« L’opérateur Filter filtre un Observable en ne laissant passer que les éléments qui réussissent un test que vous spécifiez sous la forme d’une fonction de prédicat ».

let disposeBag = DisposeBag()
  // Créez un observable d'entiers
  Observable.of(1, 2, 3, 4, 5, 6)
  // Appliquez l'opérateur filter
  .filter { 
      integer in
      integer % 2 == 0
  }
  // Abonnez-vous uniquement aux nombres pairs
  .subscribe(onNext: {
      print($0)
  })
  .disposed(by: disposeBag)

  SORTIE DE LA CONSOLE :
  2
  4
  6

Comme vous pouvez le voir dans cet exemple, nous avons créé un Observable d’entiers prédéfinis. Nous avons ensuite filtré les valeurs paires et nous nous sommes abonnés à cet Observable. La combinaison d’opérateurs est assez flexible et vous permet de composer des expressions très puissantes.

Comme autre exemple, consultez ce morceau de code avec un opérateur “flatMap”.

« L’opérateur FlatMap transforme un Observable en appliquant une fonction que vous spécifiez à chaque élément émis par l’Observable source, où cette fonction renvoie un Observable qui émet lui-même des éléments. FlatMap fusionne ensuite les émissions de ces Observables résultants, émettant ces résultats fusionnés comme sa propre séquence. »

struct Video {
      var subscribers: Variable
  }

  let disposeBag = DisposeBag()

  let cat = Video(subscribers: Variable(30))
  let bird = Video(subscribers: Variable(43))
  let dog = Video(subscribers: Variable(20))

  let channel = PublishSubject

Dans cet exemple, tout d’abord, nous avons créé la structure “Video” avec un seul paramètre observable “subscribers”. L’une des façons de récupérer des événements de ces observables est de s’abonner à chacun d’eux, mais grâce à “flatMap”, nous pouvons obtenir un résultat similaire de manière plus élégante. Nous créons donc un nouveau PublicSubject “channel” et utilisons l’opérateur “flatMap” pour obtenir un flux avec tous ces observables. Ensuite, nous nous y abonnons pour imprimer les valeurs à l’écran.
Comme je l’ai mentionné précédemment, nous pouvons combiner des opérateurs pour obtenir des fonctionnalités plus complexes. Dans ce cas, nous utilisons “filter” avant “flatMap” pour observer uniquement les vidéos dont la valeur de “subscribers” est supérieure à vingt. Par conséquent, la modification de la vidéo “dog” ne déclenche pas d’événement d’impression tant que nous ne nous y abonnons pas directement.

Pour une meilleure compréhension, consultez ce diagramme de l’opérateur “flatMap” :

Et ensuite ?

À ce stade, vous pouvez commencer à intégrer Rx dans votre application. Il vous suffit de choisir l’une des bibliothèques pour votre plateforme parmi celles disponibles ici. Elles ont toutes une documentation assez complète, mais en tant que débutant, vous pourriez avoir besoin d’informations supplémentaires pour utiliser Rx dans les meilleures conditions. Heureusement, il existe aujourd’hui sur le marché de nombreux bons livres pour différentes plateformes qui décrivent des cas d’utilisation spécifiques des bibliothèques Rx. Par exemple, si vous travaillez avec Swift comme moi, je vous recommande de consulter ce livre RxSwift créé par l’équipe de tutoriels de raywenderlich.com.