ReactiveCocoa vs RxSwift - avantages et inconvénients?

256

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

En outre, il y a eu un autre projet lancé sous le nom de RxSwift .

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

[Remarque 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 un sujet très important pour SO]

Pour commencer, mon impression initiale de la lecture de leurs Lisez-moi est la suivante:

  • En tant que quelqu'un qui connaît le "vrai" C # Rx de Microsoft, RxSwift semble beaucoup plus reconnaissable.
  • ReactiveCococa semble être parti dans son propre espace maintenant, introduisant de nouvelles abstractions telles que Signals vs SignalProducers et Lifting. D'une part, cela semble clarifier certaines situations (ce qui est un signal Hot vs Cold) mais d'autre part, cela semble augmenter la complexité du cadre un LOT
Orion Edwards
la source
Votre question demande spécifiquement des "opinions". Pourriez-vous s'il vous plaît reformuler? Je retirerai alors volontiers mon vote serré.
Sulthan
2
Vous pouvez vous débarrasser de «ajouter leurs opinions», car les différences sont des faits, pas des opinions. Ensuite, vous pouvez aimer ou détester certaines fonctionnalités de RAC / RxSwift, mais les différences sont claires.
bontoJR
1
hahaha, bonne décision concernant la "note aux mods"!
ming yeow
1
Renommer la question: différence entre ReactiveCocoa et RxSwift. Je pense que tout deviendra "fait", et cette question est héritée.
hqt
1
Même la solution commence par "C'est une très bonne question". : |
Iulian Onofrei

Réponses:

419

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 comme C #, Java ou JS.

Reactive Cocoa a été inspiré par la programmation fonctionnelle réactive , mais au cours des derniers mois, il a également été souligné 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 , selon la définition de Conal de concept. À partir de là, tout peut être réduit à la façon dont chaque framework gère les effets secondaires et quelques autres composants.

Parlons de la communauté et de la méta-technologie :

  • RAC est un projet vieux de 3 ans, né dans Objective-C plus tard porté sur Swift (avec des ponts) pour la version 3.0, après avoir complètement abandonné le travail 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 qui est importante pour RxSwift est qu'elle est sous l' organisation ReactiveX et que toutes les autres implémentations fonctionnent de la même manière, apprendre à gérer RxSwift rendra le travail avec Rx.Net, RxJava ou RxJS une tâche simple et juste une question de la syntaxe du langage. Je pourrais dire que c'est basé sur la philosophie apprendre une fois, appliquer partout .

Il est maintenant temps pour la technologie.

Entités productrices / observatrices

RAC 3.0 a 2 entités principales, Signalet SignalProducer, la première publie des événements indépendamment du fait qu'un abonné soit attaché ou non, la seconde nécessite une production starteffective de signaux / événements. Cette conception a été créée pour séparer le concept fastidieux des observables chauds et froids, qui a été source de confusion pour de nombreux développeurs. C'est pourquoi les différences peuvent être réduites à la façon dont elles gèrent les effets secondaires .

Dans RxSwift, Signalet cela se SignalProducertraduit par Observable, cela peut sembler déroutant, mais ces 2 entités sont en fait la même chose dans le monde Rx. Un design avecObservable s dans RxSwift doit être créé en considérant s'ils sont chauds ou froids, cela peut sembler une complexité inutile, mais une fois que vous avez compris comment ils fonctionnent (et encore chaud / froid / chaud ne concerne que les effets secondaires lors de la souscription / observation ) 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 introduit et c'est l' interruptionévénement quand un Signalest supprimé avant l'envoi de l'événement d'achèvement. Pour récapituler, les deux ont le type d'événement suivant:

  • Next, pour calculer la nouvelle valeur reçue
  • Error, pour calculer une erreur et terminer le flux, en désinscrivant tous les observateurs
  • Complete, pour marquer le flux comme terminé en désinscrivant tous les observateurs

RAC a en plus interruptedqui est envoyé quand un Signalest supprimé avant de terminer correctement ou avec une erreur.

Écriture manuelle

Dans RAC, Signal/ SignalProducersont des entités en lecture seule, elles ne peuvent pas être gérées de l'extérieur, c'est la même chose Observabledans RxSwift. Pour transformer un Signal/ SignalProduceren une entité accessible en écriture, vous devez utiliser la pipe()fonction 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 vous est pas familier, une bonne analogie avec Future/ Promisepeut être faite. A Futureest un espace réservé en lecture seule, comme Signal/ SignalProduceret Observable, d'autre part, a Promisepeut être rempli manuellement, comme pour pipe()et Subject.

Planificateurs

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

Composition

La composition est la caractéristique clé de la programmation réactive. La composition de 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, donc nous composons des instances de Subjectet Observableavec les mêmes opérateurs, sans souci supplémentaire.

Sur l' espace RAC, Signalet SignalProducersont 2 entités différentes et nous devons liftle SignalProducerpouvoir de composer ce qui est produit avec des instances deSignal . Les deux entités ont leurs propres opérateurs, donc lorsque vous devez mélanger des choses, vous devez vous assurer qu'un certain opérateur 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 de signal sont principalement axées sur l'événement `` suivant '', vous permettant de transformer des valeurs, de sauter, de retarder, de combiner et d'observer sur différents threads. Alors que l'API du producteur de signaux est principalement concernée par les événements du cycle de vie du signal (terminé, erreur), avec des opérations comprenant ensuite, flatMap, takeUntil et catch.

Supplémentaire

RAC a également le concept de Actionet Property, le premier est un type pour calculer les effets secondaires, principalement liés à l'interaction avec l'utilisateur, le second est intéressant lors de l'observation d'une valeur pour effectuer une tâche lorsque la valeur a changé. Dans RxSwift, le Actiontraduit à nouveau en une Observable, c'est bien illustré dans RxCocoa, une intégration des primitives Rx pour iOS et Mac. Les RAC Propertypeuvent être traduits en Variable(ouBehaviourSubject ) dans RxSwift.

Il est important de comprendre que Property/ Variableest la façon dont nous devons faire le pont entre le monde impératif et la nature déclarative de la programmation réactive, donc est parfois un composant fondamental lorsqu'il s'agit de bibliothèques tierces ou de fonctionnalités de base de l'espace iOS / Mac.

Conclusion

RAC et RxSwift sont 2 bêtes complètement différentes, la première a une longue histoire dans l'espace Cocoa et beaucoup de contributeurs, la seconde est assez jeune, mais s'appuie sur des concepts qui se sont avérés efficaces dans d'autres langages comme Java, JS ou .NET. La décision qui est la meilleure est la préférence. RAC déclare que la séparation du chaud / du froid observable était nécessaire et que c'est la caractéristique principale du cadre, RxSwift dit que l'unification de ceux-ci est meilleure que la séparation, encore une fois, il s'agit de la façon dont les effets secondaires sont gérés / exécutés.

RAC 3.0 semble avoir introduit une complexité inattendue en plus de l'objectif principal de séparer les observables chaud / froid, comme le concept d'interruption, de diviser les opérateurs entre 2 entités et d'introduire un comportement impératif comme startcommencer à produire des signaux. Pour certaines personnes, ces choses peuvent être une bonne chose ou même une fonctionnalité de tueur, pour d'autres, elles peuvent être simplement inutiles ou même dangereuses. Une autre chose à retenir est que RAC essaie de suivre autant que possible les conventions Cocoa, donc si vous êtes un développeur Cocoa expérimenté, vous devriez vous sentir plus à l'aise de travailler avec lui plutôt qu'avec RxSwift.

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

Celui qui doit être choisi est définitivement une question de préférence, d'un point de vue objectif, il est impossible de dire lequel est le meilleur. La seule façon est de lancer Xcode et de les essayer tous les deux et de choisir celui qui vous convient le mieux. Il s'agit de 2 implémentations de concepts similaires, essayant d'atteindre le même objectif: simplifier le développement logiciel.

bontoJR
la source
24
Ceci est une excellente explication, @ junior-b! Il convient également de mentionner, cependant, que RAC code les informations de type (y compris l'absence d'erreurs grâce à NoError) dans les types de flux eux-mêmes: Signal<T, E: ErrorType>contre Observable<T>. Ceci, ainsi que la séparation chaud / froid, fournit une quantité accrue d'informations au moment de la compilation que vous n'avez tout simplement pas avec RxSwift.
NachoSoto
3
Salut @nachosoto, merci pour le mot aimable. Je pense que l'ajout proposé ne conviendrait pas si bien dans une comparaison sur la programmation réactive. C'est certainement un ajout intéressant du côté du RAC, mais pour moi, RP consiste à simplifier la programmation du flux de données et les facteurs importants sont: la gestion des erreurs, le calcul asynchrone, la gestion des effets secondaires et la composition. Du point de vue du développeur, cela semble être une fonctionnalité intéressante, c'est pour clarifier le type d'erreur sur le code, cela n'améliore pas vraiment l'aspect de la gestion des erreurs du framework, c'est, bien sûr, mon humble avis.
bontoJR
3
Il convient de mentionner qu'à l'heure actuelle, il existe un manque de tutoriels décents sur RAC, mais il existe d'excellents exemples de projets pour RxSwift qui ont été décisifs pour moi.
Vadim Bulavin
1
ReactiveCocoa était bon, jusqu'à ce qu'ils introduisent des fonctions gratuites, SignalProducer, générique avec Error. J'apprends RxSwift et j'obtiens la même expérience en travaillant avec RxKotlin, RxJS
onmyway133