ReactiveCocoa vs RxSwift: ¿pros y contras?
Ahora con Swift, la gente de ReactiveCocoa lo ha reescrito en la versión 3.0 para Swift.
Además, ha surgido otro proyecto llamado RxSwift .
Me pregunto si la gente podría agregar información sobre cuáles son las diferencias en el diseño/api/filosofía de los dos marcos (por favor, en el espíritu de SO, limítese a las cosas que son ciertas, en lugar de opiniones sobre cuál es "mejor")
Para empezar, mi impresión inicial al leer su Léame es:
- Como alguien que está familiarizado con el C# Rx "real" de Microsoft, RxSwift parece mucho más reconocible.
- ReactiveCococa parece haber entrado ahora en su propio espacio, introduciendo nuevas abstracciones como Signals vs SignalProducers y Lifting. Por un lado, esto parece aclarar algunas situaciones (qué es una señal Caliente o Fría) pero, por otro lado, parece aumentar MUCHO la complejidad del marco.
Esta es una muy buena pregunta. Comparar los dos mundos es muy difícil. Rx es una adaptación de lo que son las Reactive Extensions en otros lenguajes como C#, Java o JS.
Reactive Cocoa se inspiró en la programación reactiva funcional , pero en los últimos meses también se ha señalado que está inspirado en las extensiones reactivas . El resultado es un marco que comparte algunas cosas con Rx, pero tiene nombres con origen en FRP.
Lo primero que hay que decir es que ni RAC ni RxSwift son implementaciones de Programación Reactiva Funcional , según la definición del concepto de Conal . A partir de este punto, todo se puede reducir a cómo cada marco maneja los efectos secundarios y algunos otros componentes.
Hablemos de la comunidad y de la metatecnología :
- RAC es un proyecto de 3 años, nacido en Objective-C y luego portado a Swift (con puentes) para la versión 3.0, después de abandonar por completo el trabajo en curso en Objective-C.
- RxSwift es un proyecto que tiene unos meses y parece tener impulso en la comunidad en este momento. Una cosa que es importante para RxSwift es que está bajo la organización ReactiveX y que todas las demás implementaciones funcionan de la misma manera. Aprender a manejar RxSwift hará que trabajar con Rx.Net, RxJava o RxJS sea una tarea sencilla y solo una cuestión. de la sintaxis del lenguaje. Podría decir que se basa en la filosofía de aprender una vez, aplicar en todas partes .
Ahora es el momento de las cosas tecnológicas.
Entidades productoras/observadoras
RAC 3.0 tiene 2 entidades principales: Signal
la SignalProducer
primera publica eventos independientemente de que un suscriptor esté conectado o no, la segunda requiere que start
se produzcan señales/eventos. Este diseño ha sido creado para separar el tedioso concepto de observables fríos y calientes, que ha sido fuente de confusión para muchos desarrolladores. Es por eso que las diferencias pueden reducirse a cómo manejan los efectos secundarios .
En RxSwift, Signal
y SignalProducer
se traduce como Observable
, puede parecer confuso, pero estas 2 entidades son en realidad lo mismo en el mundo Rx. Observable
Se debe crear un diseño con s en RxSwift considerando si son fríos o calientes, podría parecer una complejidad innecesaria, pero una vez que entendiste cómo funcionan (y nuevamente, caliente/frío/tibio se trata solo de los efectos secundarios al suscribirse/observar ) pueden ser domesticados.
En ambos mundos, el concepto de suscripción es básicamente el mismo, hay una pequeña diferencia que introdujo RAC y es el interruption
evento en el que Signal
se elimina antes de que se haya enviado el evento de finalización. En resumen, ambos tienen el siguiente tipo de eventos:
Next
, para calcular el nuevo valor recibidoError
, para calcular un error y completar la transmisión, cancelando la suscripción de todos los observadores.Complete
, para marcar la transmisión como completada y cancelar la suscripción de todos los observadores.
RAC además tiene interrupted
que se envía cuando Signal
se elimina antes de completarse ya sea correctamente o con un error.
Escribir manualmente
En RAC, Signal
/ SignalProducer
son entidades de solo lectura, no se pueden administrar desde afuera, lo mismo ocurre Observable
en RxSwift. Para convertir un Signal
/ SignalProducer
en una entidad que se puede escribir, debe usar la pipe()
función para devolver un elemento controlado manualmente. En el espacio Rx, este es un tipo diferente llamado Subject
.
Si el concepto de lectura/escritura le resulta desconocido, se puede hacer una buena analogía con Future
/ . Promise
A Future
es un marcador de posición de solo lectura, como Signal
/ SignalProducer
y Observable
, por otro lado, a Promise
se puede completar manualmente, como para pipe()
y Subject
.
Programadores
Esta entidad es bastante similar en ambos mundos, los mismos conceptos, pero RAC es solo en serie, en cambio, RxSwift también presenta programadores concurrentes.
Composición
La composición es la característica clave de la programación reactiva. Componer flujos es la esencia de ambos marcos; en RxSwift también se les llama secuencias .
Todas las entidades observables en RxSwift son de tipo ObservableType
, por lo que componemos instancias de Subject
y Observable
con los mismos operadores, sin ninguna preocupación adicional.
En el espacio RAC, Signal
y SignalProducer
son 2 entidades diferentes y tenemos que lift
seguir SignalProducer
para poder componer lo que se produce con instancias de Signal
. Las dos entidades tienen sus propios operadores, por lo que cuando necesitas mezclar cosas, debes asegurarte de que un determinado operador esté disponible; por otro lado, te olvidas de los observables fríos/calientes.
Acerca de esta parte, Colin Eberhardt la resumió muy bien:
Al observar la API actual, las operaciones de señal se centran principalmente en el "siguiente" evento, lo que le permite transformar valores, omitir, retrasar, combinar y observar en diferentes subprocesos. Mientras que la API del productor de señales se ocupa principalmente de los eventos del ciclo de vida de la señal (completado, error), con operaciones que incluyen then, flatMap, takeUntil y catch.
Extra
RAC también tiene el concepto de Action
y Property
, el primero es un tipo para calcular efectos secundarios, principalmente relacionados con la interacción del usuario, el segundo es interesante cuando se observa un valor para realizar una tarea cuando el valor ha cambiado. En RxSwift, esto se Action
traduce nuevamente en Observable
, esto se muestra muy bien en RxCocoa
, una integración de primitivas de Rx tanto para iOS como para Mac. Los RAC Property
se pueden traducir a Variable
(o BehaviourSubject
) en RxSwift.
Es importante entender que Property
/ Variable
es la forma que tenemos de unir el mundo imperativo con la naturaleza declarativa de la Programación Reactiva, por lo que a veces es un componente fundamental cuando se trata de bibliotecas de terceros o funcionalidades centrales del espacio iOS/Mac.
Conclusión
RAC y RxSwift son dos bestias completamente diferentes, el primero tiene una larga historia en el espacio Cocoa y muchos contribuyentes, el segundo es bastante joven, pero se basa en conceptos que han demostrado ser efectivos en otros lenguajes como Java, JS o .NETO. La decisión sobre cuál es mejor depende de la preferencia. RAC afirma que la separación de los observables frío/calor era necesaria y esa es la característica principal del marco, RxSwift dice que la unificación de ellos es mejor que la separación, nuevamente se trata solo de cómo se manejan/realizan los efectos secundarios.
RAC 3.0 parece haber introducido cierta complejidad inesperada además del objetivo principal de separar observables fríos y calientes, como el concepto de interrupción, dividir operadores entre 2 entidades e introducir algún comportamiento imperativo como start
comenzar a producir señales. Para algunas personas, estas cosas pueden ser algo agradable o incluso una característica excelente, para otras pueden ser simplemente innecesarias o incluso peligrosas. Otra cosa para recordar es que RAC está tratando de mantenerse al día con las convenciones de Cocoa tanto como sea posible, por lo que si es un desarrollador experimentado de Cocoa, debería sentirse más cómodo trabajando con él en lugar de con RxSwift.
RxSwift, por otro lado, vive con todas las desventajas, como los observables fríos y calientes, pero también las cosas buenas de Reactive Extensions. Pasar de RxJS, RxJava o Rx.Net a RxSwift es algo simple, todos los conceptos son iguales, por lo que esto hace que encontrar material sea bastante interesante, tal vez el mismo problema al que te enfrentas ahora haya sido resuelto por alguien en RxJava y la solución. Se puede volver a aplicar teniendo en cuenta la plataforma.
Cuál hay que elegir es definitivamente una cuestión de preferencia, desde una perspectiva objetiva es imposible decir cuál es mejor. La única forma es iniciar Xcode, probar ambos y elegir el que le resulte más cómodo para trabajar. Son 2 implementaciones de conceptos similares, intentando conseguir el mismo objetivo: simplificar el desarrollo de software.