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 Signal
e SignalProducer
, la prima pubblica gli eventi indipendentemente dal fatto che un abbonato sia collegato o meno, la seconda richiede start
che 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, Signal
e SignalProducer
tradotto in Observable
, potrebbe sembrare confuso, ma queste 2 entità sono in realtà la stessa cosa nel mondo Rx. Un design con Observable
s 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' interruption
evento in cui un oggetto Signal
viene 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 interrupted
viene inviato quando Signal
viene eliminato a prima di essere completato correttamente o con un errore.
Scrittura manuale
In RAC, Signal
/ SignalProducer
sono entità di sola lettura, non possono essere gestite dall'esterno, la stessa cosa è per Observable
RxSwift. Per trasformare un Signal
/ SignalProducer
in 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
/ SignalProducer
e Observable
, d'altra parte, Promise
può 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 Subject
e Observable
con gli stessi operatori, senza alcuna preoccupazione aggiuntiva.
Nel settore dello spazio RAC, Signal
e SignalProducer
sono 2 entità diverse e dobbiamo lift
su SignalProducer
di 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 Action
e 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 Action
nuovo si traduce in un Observable
, questo è ben mostrato in RxCocoa
, un'integrazione di primitive Rx sia per iOS che per Mac. I RAC Property
possono 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 start
iniziare 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.