ReactiveCocoa vs RxSwift - pro e contro?


256

Quindi ora con swift, le persone ReactiveCocoa lo hanno riscritto nella versione 3.0 per swift

Inoltre, è stato lanciato un altro progetto chiamato RxSwift .

Mi chiedo se le persone potrebbero aggiungere informazioni su quali siano le differenze nel design / api / filosofia dei due quadri (per favore, nello spirito di SO, attenersi a cose vere, piuttosto che opinioni su quale sia "migliore")

[Nota per le mod StackOverflow: questa domanda ha risposte definitive, la risposta è le differenze tra i due framework. Penso che sia anche molto in tema per SO]

Per iniziare, la mia impressione iniziale dalla lettura dei loro file Leggimi è:

  • Come qualcuno che ha familiarità con il "vero" C # Rx di microsoft, RxSwift sembra molto più riconoscibile.
  • ReactiveCococa sembra essere andato nel suo spazio proprio ora, introducendo nuove astrazioni come Signals vs SignalProducers e Lifting. Da un lato questo sembra chiarire alcune situazioni (che cosa è un segnale caldo vs freddo) ma dall'altro sembra che ciò aumenti molto la complessità del framework

La tua domanda richiede specificamente "opinioni". Potresti riformulare per favore? Ritirerò volentieri il mio voto ravvicinato.
Sulthan,

2
Puoi sbarazzarti di "aggiungere le loro opinioni", perché le differenze sono fatti, non opinioni. Quindi puoi apprezzare o non apprezzare alcune funzionalità di RAC / RxSwift, ma le differenze sono cristalline.
bontoJR,

1
ahahah, buona mossa per quanto riguarda la "nota ai mod"!
ming yeow

1
Rinomina domanda: differenza tra ReactiveCocoa e RxSwift. Penso che tutto diventerà "fatto", e questa domanda è eredità.
hqt

1
Anche la soluzione inizia con "Questa è un'ottima domanda". : |
Iulian Onofrei,

Risposte:


419

Questa è un'ottima domanda Il confronto tra i due mondi è molto difficile. Rx è una porta di ciò che le estensioni reattive sono in altre lingue come C #, Java o JS.

Reactive Cocoa è stato ispirato dalla Programmazione reattiva funzionale , ma negli ultimi mesi è stato anche indicato come ispirato dalle estensioni reattive . Il risultato è un framework che condivide alcune cose con Rx, ma ha nomi con origini in FRP.

La prima cosa da dire è che né RAC né RxSwift sono implementazioni di Programmazione Reattiva Funzionale , secondo la definizione di Conal del concetto. Da questo punto tutto può essere ridotto al modo in cui ciascun framework gestisce gli effetti collaterali e alcuni altri componenti.

Parliamo della community e delle cose meta-tecnologiche :

  • RAC è un progetto di 3 anni, nato in Objective-C successivamente portato su Swift (con bridge) per la versione 3.0, dopo aver completamente abbandonato il lavoro in corso su Objective-C.
  • RxSwift è un progetto di pochi mesi e sembra avere un momento nella comunità in questo momento. Una cosa che è importante per RxSwift è che è all'interno dell'organizzazione ReactiveX e che tutte le altre implementazioni funzionano allo stesso modo, imparare a gestire RxSwift renderà il lavoro con Rx.Net, RxJava o RxJS un compito semplice e solo una questione della sintassi del linguaggio. Potrei dire che si basa sulla filosofia imparare una volta, applicare ovunque .

Ora è il momento delle cose tecnologiche.

Produrre / osservare entità

RAC 3.0 ha 2 entità principali Signale SignalProducer, la prima pubblica gli eventi indipendentemente dal fatto che un abbonato sia collegato o meno, la seconda richiede startche vengano effettivamente prodotti segnali / eventi. Questo design è stato creato per separare il noioso concetto di osservabili caldi e freddi, che è stato fonte di confusione per molti sviluppatori. Questo è il motivo per cui le differenze possono essere ridotte al modo in cui gestiscono gli effetti collaterali .

In RxSwift, Signale SignalProducertradotto in Observable, potrebbe sembrare confuso, ma queste 2 entità sono in realtà la stessa cosa nel mondo Rx. Un design con Observables in RxSwift deve essere creato considerando che sono caldi o freddi, potrebbe sembrare una complessità non necessaria, ma una volta capito come funzionano (e di nuovo caldo / freddo / caldo riguarda solo gli effetti collaterali durante la sottoscrizione / osservazione ) possono essere domati.

In entrambi i mondi, il concetto di abbonamento è sostanzialmente lo stesso, c'è una piccola differenza introdotta da RAC ed è l' interruptionevento in cui un oggetto Signalviene eliminato prima dell'invio dell'evento di completamento. Per ricapitolare entrambi hanno il seguente tipo di eventi:

  • Next, per calcolare il nuovo valore ricevuto
  • Error, per calcolare un errore e completare il flusso, annullando l'iscrizione a tutti gli osservatori
  • Complete, per contrassegnare lo stream come completato annullando l'iscrizione a tutti gli osservatori

Inoltre, RAC interruptedviene inviato quando Signalviene eliminato a prima di essere completato correttamente o con un errore.

Scrittura manuale

In RAC, Signal/ SignalProducersono entità di sola lettura, non possono essere gestite dall'esterno, la stessa cosa è per ObservableRxSwift. Per trasformare un Signal/ SignalProducerin un'entità scrivibile, è necessario utilizzare la pipe()funzione per restituire un oggetto controllato manualmente. Nello spazio Rx, questo è un tipo diverso chiamato Subject.

Se il concetto di lettura / scrittura sembra sconosciuto, è possibile creare una bella analogia con Future/ Promise. A Futureè un segnaposto di sola lettura, come Signal/ SignalProducere Observable, d'altra parte, Promisepuò essere eseguito manualmente, come per pipe()e Subject.

schedulatori

Questa entità è praticamente simile in entrambi i mondi, stessi concetti, ma RAC è solo seriale, invece RxSwift offre anche programmatori simultanei.

Composizione

La composizione è la caratteristica chiave della programmazione reattiva. La composizione di flussi è l'essenza di entrambi i framework, in RxSwift sono anche chiamati sequenze .

Tutte le entità osservabili in RxSwift sono di tipo ObservableType, quindi componiamo istanze di Subjecte Observablecon gli stessi operatori, senza alcuna preoccupazione aggiuntiva.

Nel settore dello spazio RAC, Signale SignalProducersono 2 entità diverse e dobbiamo liftsu SignalProducerdi essere in grado di comporre ciò che viene prodotto con le istanze di Signal. Le due entità hanno i propri operatori, quindi quando è necessario mescolare le cose, è necessario assicurarsi che un determinato operatore sia disponibile, dall'altro lato si dimenticano gli osservabili caldo / freddo.

A proposito di questa parte, Colin Eberhardt lo ha riassunto bene:

Osservando l'API corrente, le operazioni del segnale sono principalmente focalizzate sull'evento "successivo", che consente di trasformare valori, saltare, ritardare, combinare e osservare su thread diversi. Considerando che l'API del produttore del segnale si occupa principalmente degli eventi del ciclo di vita del segnale (completato, errore), con operazioni tra cui then, flatMap, takeUntil e catch.

Extra

RAC ha anche il concetto di Actione Property, il primo è un tipo per calcolare gli effetti collaterali, principalmente relativi all'interazione dell'utente, il secondo è interessante quando si osserva un valore per eseguire un'attività quando il valore è cambiato. In RxSwift il Actionnuovo si traduce in un Observable, questo è ben mostrato in RxCocoa, un'integrazione di primitive Rx sia per iOS che per Mac. I RAC Propertypossono essere tradotti in Variable(o BehaviourSubject) in RxSwift.

È importante capire che Property/ Variableè il modo in cui dobbiamo collegare il mondo imperativo alla natura dichiarativa della programmazione reattiva, quindi a volte è un componente fondamentale quando si tratta di librerie di terze parti o funzionalità di base dello spazio iOS / Mac.

Conclusione

RAC e RxSwift sono 2 bestie completamente diverse, la prima ha una lunga storia nello spazio Cocoa e molti collaboratori, la seconda è piuttosto giovane, ma si basa su concetti che si sono dimostrati efficaci in altre lingue come Java, JS o .NETTO. La decisione su quale sia la migliore è di preferenza. RAC afferma che la separazione tra caldo / freddo osservabile era necessaria e che è la caratteristica principale del framework, RxSwift afferma che l'unificazione di essi è migliore della separazione, ancora una volta riguarda il modo in cui gli effetti collaterali sono gestiti / eseguiti.

RAC 3.0 sembra aver introdotto una complessità inaspettata oltre al principale obiettivo di separare osservabili caldo / freddo, come il concetto di interruzione, suddividere gli operatori tra 2 entità e introdurre alcuni comportamenti imperativi come startiniziare a produrre segnali. Per alcune persone queste cose possono essere una cosa carina da avere o anche una caratteristica killer, per altre possono essere semplicemente inutili o addirittura pericolose. Un'altra cosa da ricordare è che RAC sta cercando di tenere il passo con le convenzioni Cocoa il più possibile, quindi se sei un esperto Cocoa Dev, dovresti sentirti più a tuo agio nel lavorarci piuttosto che in RxSwift.

RxSwift invece vive con tutti gli aspetti negativi come osservabili caldo / freddo, ma anche le cose buone delle estensioni reattive. Passare da RxJS, RxJava o Rx.Net a RxSwift è una cosa semplice, tutti i concetti sono gli stessi, quindi questo rende il materiale piuttosto interessante, forse lo stesso problema che stai affrontando ora, è stato risolto da qualcuno in RxJava e la soluzione può essere riapplicato prendendo in considerazione la piattaforma.

Quale deve essere scelto è sicuramente una questione di preferenza, da una prospettiva obiettiva è impossibile dire quale sia la migliore. L'unico modo è lanciare Xcode e provarli entrambi e scegliere quello con cui ci si sente più a proprio agio. Sono 2 implementazioni di concetti simili, cercando di raggiungere lo stesso obiettivo: semplificare lo sviluppo del software.


24
Questa è un'ottima spiegazione, @ junior-b! Vale anche la pena ricordare, tuttavia, che RAC codifica le informazioni sui tipi (inclusa la mancanza di errori grazie NoError) nei tipi di flusso stessi: Signal<T, E: ErrorType>contro Observable<T>. Questo, così come la separazione caldo / freddo, fornisce una maggiore quantità di informazioni in fase di compilazione che non si ha RxSwift.
NachoSoto,

3
Ciao @nachosoto, grazie per la gentile parola. Penso che l'aggiunta proposta non si adatterebbe così bene in un confronto sulla programmazione reattiva. È sicuramente una bella aggiunta da parte del RAC, ma per me RP riguarda la semplificazione della programmazione del flusso di dati e fattori importanti sono: gestione degli errori, calcolo asincrono, gestione degli effetti collaterali e composizione. Dal punto di vista dello sviluppatore sembra una bella caratteristica, questo serve a chiarire il tipo di errore nel codice, non sta davvero migliorando l'aspetto della gestione degli errori del framework, questa è ovviamente la mia modesta opinione.
bontoJR,

3
Vale la pena ricordare che ad oggi mancano tutorial decenti su RAC, tuttavia ci sono alcuni grandi progetti di esempio per RxSwift che è stato decisivo per me.
Vadim Bulavin,

1
ReactiveCocoa è stato buono, fino a quando non hanno introdotto funzioni libere, SignalProducer, generico con errore. Imparo RxSwift e ottengo la stessa esperienza lavorando con RxKotlin, RxJS
onmyway133
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.