Así que ahora con swift, la gente de ReactiveCocoa lo ha reescrito en la versión 3.0 para swift
Además, ha habido otro proyecto creado llamado RxSwift .
Me pregunto si las personas podrían 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, atenerse a las cosas que son verdaderas, en lugar de opiniones sobre cuál es el "mejor")
[Nota para las modificaciones de StackOverflow: esta pregunta TIENE respuestas definitivas, la respuesta son las diferencias entre los dos marcos. Creo que también es un tema muy importante para SO]
Para comenzar, mi impresión inicial al leer sus Léame es:
- Como alguien que está familiarizado con el "real" C # Rx de microsoft, RxSwift se ve mucho más reconocible.
- ReactiveCococa parece haberse ido a su propio espacio ahora, introduciendo nuevas abstracciones como Signals vs SignalProducers y Lifting. Por un lado, esto parece aclarar algunas situaciones (qué es una señal de calor frente a frío), pero por otro lado, esto parece aumentar la complejidad del marco MUCHO
swift
reactive-programming
rx-swift
reactive-cocoa-3
Orion Edwards
fuente
fuente
Respuestas:
Esta es una muy buena pregunta. Comparar los dos mundos es muy difícil. Rx es un puerto de lo que son las extensiones reactivas en otros lenguajes como C #, Java o JS.
Reactive Cocoa se inspiró en la programación funcional reactiva , pero en los últimos meses también se ha inspirado en las extensiones reactivas . El resultado es un marco que comparte algunas cosas con Rx, pero tiene nombres con orígenes en FRP.
Lo primero que hay que decir es que ni RAC ni RxSwift son implementaciones de programación funcional reactiva , según la definición del concepto de Conal . Desde este punto, todo se puede reducir a cómo cada marco maneja los efectos secundarios y algunos otros componentes.
Hablemos de la comunidad y las cosas meta-tecnológicas :
Ahora es el momento de las cosas tecnológicas.
Entidades productoras / observadoras
RAC 3.0 tiene 2 entidades principales,
Signal
ySignalProducer
la primera publica eventos independientemente de si un suscriptor está conectado o no, la segunda requierestart
que 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 se pueden reducir a la forma en que manejan los efectos secundarios .En RxSwift,
Signal
y seSignalProducer
traduce enObservable
, puede sonar confuso, pero estas 2 entidades son en realidad lo mismo en el mundo de Rx. SeObservable
debe crear un diseño con s en RxSwift teniendo en cuenta que si hace calor o frío, puede sonar como una complejidad innecesaria, pero una vez que haya entendido cómo funcionan (y nuevamente caliente / frío / cálido 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 RAC introdujo y es el
interruption
evento cuandoSignal
se elimina antes de que se envíe el evento de finalización. Para recapitular, ambos tienen el siguiente tipo de eventos:Next
, para calcular el nuevo valor recibidoError
, para calcular un error y completar la secuencia, cancelando la suscripción de todos los observadoresComplete
, para marcar la secuencia como completada cancelando la suscripción de todos los observadoresAdemás, RAC tiene
interrupted
que se envía cuandoSignal
se elimina a antes de completar correctamente o con un error.Escribir manualmente
En RAC,
Signal
/SignalProducer
son entidades de solo lectura, no se pueden administrar desde afuera, lo mismo es paraObservable
RxSwift. Para convertir aSignal
/SignalProducer
en una entidad que se pueda escribir, debe usar lapipe()
función para devolver un elemento controlado manualmente. En el espacio Rx, este es un tipo diferente llamadoSubject
.Si el concepto de lectura / escritura no le resulta familiar, se puede hacer una buena analogía con
Future
/Promise
. AFuture
es un marcador de posición de solo lectura, comoSignal
/SignalProducer
yObservable
, por otro lado, aPromise
se puede cumplir manualmente, como parapipe()
ySubject
.Programadores
Esta entidad es bastante similar en ambos mundos, los mismos conceptos, pero RAC es solo de serie, en cambio, RxSwift presenta también planificadores simultáneos.
Composición
La composición es la característica clave de la programación reactiva. La composición de 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 componimos instanciasSubject
yObservable
con los mismos operadores, sin ninguna preocupación adicional.En el espacio RAC,
Signal
ySignalProducer
son 2 entidades diferentes y tenemos quelift
enSignalProducer
ser capaz de componer lo que se produce con las instancias deSignal
. Las dos entidades tienen sus propios operadores, por lo que cuando necesita mezclar cosas, debe asegurarse de que un determinado operador esté disponible, por otro lado, se olvida de los observables frío / calor.Sobre esta parte, Colin Eberhardt lo resumió amablemente:
Extra
RAC también tiene el concepto de
Action
yProperty
, el primero es un tipo para calcular los 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 el RxSwiftAction
se traduce en un nuevoObservable
, esto está muy bien muestra enRxCocoa
, una integración de las primitivas Rx tanto para iOS y Mac. Los RACProperty
se pueden traducir aVariable
(oBehaviourSubject
) en RxSwift.Es importante comprender que
Property
/Variable
es la forma en que tenemos que 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 2 bestias diferentes, la primera tiene una larga historia en el espacio Cocoa y muchos contribuyentes, la segunda es bastante joven, pero se basa en conceptos que han demostrado ser efectivos en otros lenguajes como Java, JS o .RED. La decisión sobre cuál es mejor es la preferencia. RAC afirma que la separación de calor / frío observable 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 una complejidad inesperada además del objetivo principal de separar los observables frío / calor, como el concepto de interrupción, dividir los operadores entre 2 entidades e introducir un comportamiento imperativo como
start
comenzar a producir señales. Para algunas personas, estas cosas pueden ser algo agradable o incluso una característica asesina, para otras pueden ser 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 usted es un Cocoa Dev experimentado, debería sentirse más cómodo para trabajar con él en lugar de RxSwift.RxSwift, por otro lado, vive con todas las desventajas, como los observables de frío / calor, pero también las cosas buenas de las extensiones reactivas. Pasar de RxJS, RxJava o Rx.Net a RxSwift es algo simple, todos los conceptos son los mismos, por lo que esto hace que encontrar material sea bastante interesante, tal vez el mismo problema que enfrenta ahora, alguien en RxJava lo haya resuelto y la solución se puede volver a aplicar teniendo en cuenta la plataforma.
Cuál tiene que ser elegido es definitivamente una cuestión de preferencia, desde una perspectiva objetiva es imposible saber cuál es mejor. La única forma es disparar Xcode y probar ambos y elegir el que se sienta más cómodo para trabajar. Son 2 implementaciones de conceptos similares, que intentan alcanzar el mismo objetivo: simplificar el desarrollo de software.
fuente
NoError
) en los tipos de flujo en sí:Signal<T, E: ErrorType>
versusObservable<T>
. Esto, así como la separación frío / calor, proporciona una mayor cantidad de información en tiempo de compilación que simplemente no tieneRxSwift
.