web-dev-qa-db-fra.com

ReactiveCocoa vs RxSwift - avantages et inconvénients?

Alors maintenant, avec Swift, les ReactiveCocoa l'ont réécrit dans la version 3.0 pour Swift

En outre, il y a eu un autre projet appelé - RxSwift .

Je me demande si les gens pourraient ajouter des informations sur les différences de conception/interface/philosophie des deux cadres (s'il vous plaît, dans l'esprit de SO, tenez-vous-en aux choses qui sont vraies plutôt qu'aux opinions sur ce qui est "le meilleur")

[Note pour les mods StackOverflow: Cette question a des réponses définitives, la réponse est la différence entre les deux frameworks. Je pense que c'est aussi très sur le sujet pour SO]

Pour commencer, mon impression initiale à la lecture de leur fichier ReadMe est la suivante:

  • RxSwift, qui connaît bien la "vraie" Rx C # de Microsoft, est beaucoup plus reconnaissable.
  • ReactiveCococa semble avoir explosé dans son propre espace, en introduisant de nouvelles abstractions telles que Signals vs SignalProducers et Lifting. D'une part, cela semble clarifier certaines situations (qu'est-ce qu'un signal Hot vs Cold), mais d'autre part, cela semble augmenter la complexité du cadre BEAUCOUP
247
Orion Edwards

C'est une très bonne question. Comparer les deux mondes est très difficile. Rx est un portage de ce que sont les extensions réactives dans d'autres langages tels que C #, Java ou JS.

Le cacao réactif a été inspiré par Programmation réactive fonctionnelle, mais au cours des derniers mois, il a également été désigné comme inspiré par les extensions réactives. Le résultat est un cadre qui partage certaines choses avec Rx, mais qui a des noms d'origine dans FRP.

La première chose à dire est que ni RAC ni RxSwift ne sont des implémentations de Programmation Réactive Fonctionnelle, conformément à définition de Conal du concept. À partir de ce moment, tout peut être réduit à la manière dont chaque framework gère les effets secondaires et quelques autres composants.

Parlons de la communauté et meta-tech stuff:

  • RAC est un projet vieux de 3 ans, né dans Objective-C et porté plus tard sur Swift (avec ponts) pour la version 3.0, après avoir complètement abandonné les travaux en cours sur Objective-C.
  • RxSwift est un projet vieux de quelques mois et semble avoir un élan dans la communauté en ce moment. Une chose importante pour RxSwift est qu’elle se trouve sous l’organisation ReactiveX et que toutes les autres implémentations fonctionnent de la même manière. En apprenant à traiter avec RxSwift, vous pourrez travailler avec Rx.Net, RxJava ou RxJS. une tâche simple et juste une question de syntaxe de langage. Je pourrais dire que cela est basé sur la philosophie apprendre une fois, appliquer partout.

Il est maintenant temps de passer aux choses techniques.

Entités productrices/observatrices

Le RAC 3.0 a 2 entités principales, Signal et SignalProducer, la première publie des événements, qu'un abonné soit connecté ou non, la seconde nécessite un start pour que les signaux/événements soient réellement produits. Cette conception a été créée pour séparer le concept fastidieux d’observables chauds et froids, source de confusion pour de nombreux développeurs. C'est pourquoi les différences peuvent être réduites à la manière dont elles gèrent les effets secondaires .

Dans RxSwift, Signal et SignalProducer se traduisent par Observable, cela peut sembler déroutant, mais ces 2 entités sont en réalité la même chose dans le monde des Rx. Un design avec Observables dans RxSwift doit être créé, car chaud ou froid, cela peut sembler une complexité inutile, mais une fois que vous avez compris comment ils fonctionnent (et encore chaud/froid/chaud, ce sont les effets secondaires en souscrivant/observant), ils peuvent être apprivoisés.

Dans les deux mondes, le concept d'abonnement est fondamentalement le même, il y a une petite différence que RAC a introduite et est l'événement interruption lorsqu'un événement Signal est supprimé avant l'envoi de l'événement d'achèvement. Pour récapituler, les deux types d'événements sont les suivants:

  • Next, pour calculer la nouvelle valeur reçue
  • Error, pour calculer une erreur et compléter le flux, en désabonnant tous les observateurs
  • Complete, pour marquer le flux comme terminé, désinscription de tous les observateurs

De plus, le RAC a interrupted envoyé lorsqu’un Signal est supprimé avant d’être terminé correctement ou avec une erreur.

Écrire manuellement

Dans RAC, Signal/SignalProducer sont des entités en lecture seule, elles ne peuvent pas être gérées de l'extérieur. Même chose pour Observable dans RxSwift. Pour transformer une Signal/SignalProducer en une entité en écriture, vous devez utiliser la fonction pipe() pour renvoyer un élément contrôlé manuellement. Sur l’espace Rx, il s’agit d’un type différent appelé Subject.

Si le concept de lecture/écriture ne semble pas familier, une analogie de Nice avec Future/Promise peut être réalisée. Un Future est un espace réservé en lecture seule, comme Signal/SignalProducer et Observable, par contre, un Promise peut être rempli manuellement, comme pour pipe() et Subject.

Planificateurs

Cette entité est à peu près similaire dans les deux mondes, les mêmes concepts, mais RAC est en série uniquement. RxSwift présente également des programmateurs simultanés.

Composition

La composition est la principale caractéristique de la programmation réactive. La composition des flux est l’essence des deux frameworks. Dans RxSwift, ils sont également appelés séquences.

Toutes les entités observables dans RxSwift sont de type ObservableType, nous composons donc des instances de Subject et Observable avec les mêmes opérateurs, sans souci supplémentaire.

Sur l'espace RAC, Signal et SignalProducer sont deux entités différentes et nous devons lift sur SignalProducer pour pouvoir composer ce qui est produit avec des instances de Signal . Les deux entités ont leurs propres opérateurs. Ainsi, lorsque vous devez mélanger des objets, vous devez vous assurer qu'un opérateur donné est disponible, de l'autre côté, vous oubliez les observables chaud/froid.

À propos de cette partie, Colin Eberhardt l'a bien résumé:

En regardant l’API actuelle, les opérations sur les signaux sont principalement axées sur l’événement "next", ce qui vous permet de transformer les valeurs, d’éviter, de retarder, de combiner et d’observer sur différents threads. Considérant que l’API du producteur de signal est principalement concernée par les événements du cycle de vie du signal (terminé, erreur), avec des opérations incluant ensuite, flatMap, takeUntil et catch.

Supplémentaire

RAC a également le concept de Action et Property, le premier est un type permettant de calculer les effets secondaires, principalement relatifs à l'interaction utilisateur, le second est intéressant lorsqu'il s'agit d'observer une valeur pour effectuer une tâche lorsque la valeur a modifié. Dans RxSwift, la Action est à nouveau traduite en Observable, ce qui est bien illustré dans RxCocoa, une intégration de primitives Rx pour iOS et Mac. Le Property du RAC peut être traduit en Variable (ou BehaviourSubject) dans RxSwift.

Il est important de comprendre que Property/Variable est le moyen par lequel nous devons relier le monde impératif à la nature déclarative de la programmation réactive. Il est donc parfois fondamental de traiter les bibliothèques tierces ou les fonctionnalités essentielles de la programmation. l'espace iOS/Mac.

Conclusion

RAC et RxSwift sont deux bêtes complètement différentes, la première a une longue histoire dans l’espace Cocoa et beaucoup de contributeurs, la dernière est assez jeune, mais repose sur des concepts qui se sont révélés efficaces dans d’autres langages tels que Java, JS ou. .NET. La décision sur ce qui est le mieux est de préférence. RAC déclare que la séparation entre observable chaud/froid était nécessaire et qu’il s’agit de la caractéristique essentielle du cadre, RxSwift indique que leur unification est meilleure que la séparation; il s’agit là encore de la gestion des effets secondaires.

RAC 3.0 semble avoir introduit une complexité inattendue en plus du principal objectif de séparer les observables chaud/froid, comme le concept d'interruption, de scinder les opérateurs entre deux entités et d'introduire un comportement impératif comme start pour commencer à produire des signaux. Pour certaines personnes, ces choses peuvent être une bonne chose à avoir ou même une fonctionnalité tueur, pour d'autres, elles peuvent être simplement inutiles ou même dangereuses. Une autre chose à retenir est que RAC essaie de suivre les conventions Cocoa autant que possible. Ainsi, si vous êtes un développeur expérimenté dans Cocoa, vous devriez sentir plus confortable à utiliser que RxSwift.

RxSwift, quant à lui, présente tous les inconvénients, comme les observables chaud/froid, mais aussi les avantages des extensions réactives. Passer de RxJS, RxJava ou Rx.Net à RxSwift est une chose simple, tous les concepts sont identiques, cela rend donc la recherche de matériel assez intéressante, peut-être que le même problème que vous rencontrez maintenant a été résolu par quelqu'un de RxJava et que la solution peut être réappliqué en tenant compte de la plate-forme.

Ce qui doit être choisi est certainement une question de préférence, d'un point de vue objectif est impossible de dire lequel est le meilleur. La seule façon de procéder consiste à renvoyer Xcode, à essayer les deux et à choisir celui avec lequel vous vous sentirez le plus à l'aise. Ce sont 2 implémentations de concepts similaires, essayant d'atteindre le même objectif: simplifier le développement logiciel.

408
bontoJR