To jest bardzo dobre pytanie. Porównywanie dwóch światów jest bardzo trudne. Rx to port Reaktywnych rozszerzeń w innych językach, takich jak C #, Java lub JS.
Reactive Cocoa został zainspirowany przez funkcjonalne programowanie reaktywne , ale w ostatnich miesiącach został również wskazany jako zainspirowany również przez Reactive Extensions . Rezultatem jest struktura, która dzieli niektóre rzeczy z Rx, ale ma nazwy pochodzące z FRP.
Pierwszą rzeczą do powiedzenia jest to, że ani RAC, ani RxSwift nie są implementacjami Funkcjonalnego Reaktywnego Programowania , zgodnie z definicją Conala . Od tego momentu wszystko można sprowadzić do tego, jak każda struktura obsługuje efekty uboczne i kilka innych składników.
Porozmawiajmy o społeczności i rzeczach związanych z meta-technologią :
- RAC to 3-letni projekt, który powstał w Objective-C, później przeniesiony do Swift (z mostami) w wersji 3.0, po całkowitym porzuceniu trwających prac nad Objective-C.
- RxSwift to kilkumiesięczny projekt i wydaje się, że ma teraz rozpęd w społeczności. Jedną z ważnych rzeczy dla RxSwift jest to, że należy do organizacji ReactiveX i że wszystkie inne implementacje działają w ten sam sposób. Nauczenie się, jak radzić sobie z RxSwift sprawi, że praca z Rx.Net, RxJava lub RxJS będzie prostym zadaniem i tylko kwestią składni języka. Mógłbym powiedzieć, że opiera się na filozofii, ucz się raz, stosuj wszędzie .
Teraz czas na rzeczy techniczne.
Produkcja / obserwacja podmiotów
RAC 3.0 ma 2 główne jednostki, Signal
a SignalProducer
pierwsza publikuje zdarzenia bez względu na to, czy subskrybent jest przyłączony czy nie, a druga wymaga start
wygenerowania sygnałów / zdarzeń. Ten projekt został stworzony, aby oddzielić nużącą koncepcję obserwowalnych na gorąco i na zimno, co było źródłem zamieszania dla wielu programistów. Dlatego różnice można ograniczyć do sposobu radzenia sobie z efektami ubocznymi .
W RxSwift Signal
i SignalProducer
przekłada się na Observable
, może to zabrzmieć myląco, ale te dwie istoty są w rzeczywistości takie same w świecie Rx. Projekt z Observable
R w RxSwift musi zostać utworzony, biorąc pod uwagę, czy są gorące czy zimne, może to zabrzmieć jako niepotrzebna złożoność, ale gdy zrozumiesz, jak działają (i ponownie gorący / zimny / ciepły dotyczy tylko skutków ubocznych podczas subskrybowania / obserwowania ) można je oswoić.
W obu światach koncepcja subskrypcji jest w zasadzie taka sama, istnieje jedna niewielka różnica, którą wprowadził RAC, i jest to interruption
wydarzenie, w którym a Signal
jest usuwane przed wysłaniem zdarzenia zakończenia. Podsumowując, oba mają następujące rodzaje zdarzeń:
Next
, aby obliczyć nową otrzymaną wartość
Error
, aby obliczyć błąd i ukończyć strumień, anulując subskrypcję wszystkich obserwatorów
Complete
, aby oznaczyć strumień jako zakończony, anulując subskrypcję wszystkich obserwatorów
RAC dodatkowo ma interrupted
to, że jest wysyłane, gdy a Signal
jest usuwane przed ukończeniem poprawnie lub z błędem.
Pisanie ręczne
W RAC Signal
/ SignalProducer
są jednostkami tylko do odczytu, nie można nimi zarządzać z zewnątrz, to samo dotyczy Observable
RxSwift. Aby zmienić a Signal
/ SignalProducer
w jednostkę, która może zapisywać, musisz użyć pipe()
funkcji, aby zwrócić ręcznie sterowany element. W przestrzeni Rx jest to inny typ o nazwie Subject
.
Jeśli koncepcja odczytu / zapisu wydaje się nieznana, można dokonać przyjemnej analogii z Future
/ Promise
. Future
Jest tylko do odczytu zastępczy, jak Signal
/ SignalProducer
a Observable
, z drugiej strony, Promise
mogą być wypełniane ręcznie, jak na pipe()
i Subject
.
Harmonogramy
Ta jednostka jest bardzo podobna w obu światach, w tych samych koncepcjach, ale RAC jest tylko szeregowy, zamiast tego RxSwift oferuje również współbieżne harmonogramy.
Kompozycja
Kompozycja jest kluczową cechą programowania reaktywnego. Komponowanie strumieni jest istotą obu struktur, w RxSwift są one również nazywane sekwencjami .
Wszystkie podmioty RxSwift obserwowalne są typu ObservableType
, więc komponować wystąpień Subject
i Observable
z tych samych operatorów, bez żadnych dodatkowych obaw.
Na przestrzeni RAC, Signal
i SignalProducer
są 2 różne podmioty i musimy lift
na SignalProducer
, aby móc komponować co jest produkowane z wystąpień Signal
. Oba byty mają swoich operatorów, więc kiedy musisz mieszać różne rzeczy, musisz upewnić się, że określony operator jest dostępny, z drugiej strony zapominasz o obserwowalnych temperaturach na gorąco i na zimno.
O tej części Colin Eberhardt ładnie to podsumował:
Patrząc na bieżący interfejs API, operacje sygnału koncentrują się głównie na zdarzeniu „następnym”, umożliwiając przekształcanie wartości, pomijanie, opóźnianie, łączenie i obserwowanie różnych wątków. Podczas gdy interfejs API producenta sygnału dotyczy głównie zdarzeń cyklu życia sygnału (zakończonych, błędów), a także operacji, takich jak flatMap, takeUntil i catch.
Dodatkowy
RAC ma również koncepcję, Action
a Property
ten pierwszy jest typem do obliczania skutków ubocznych, głównie związanych z interakcją użytkownika, ten drugi jest interesujący, gdy obserwuje się wartość w celu wykonania zadania, gdy wartość się zmieniła. W RxSwift Action
ponownie przekłada się na Observable
, jest to dobrze pokazane RxCocoa
, integracja prymitywów Rx na iOS i Mac. RAC Property
można przetłumaczyć na Variable
(lub BehaviourSubject
) w RxSwift.
Ważne jest, aby zrozumieć, że Property
/ Variable
to sposób, w jaki musimy połączyć imperatywny świat z deklaratywnym charakterem Reactive Programming, więc czasami jest to podstawowy element w kontaktach z bibliotekami stron trzecich lub podstawowymi funkcjami przestrzeni iOS / Mac.
Wniosek
RAC i RxSwift to 2 kompletnie różne bestie, ta pierwsza ma długą historię w przestrzeni kakaowej i wielu współpracowników, ta druga jest dość młoda, ale opiera się na koncepcjach, które okazały się skuteczne w innych językach, takich jak Java, JS lub .NETTO. Decyzja, która opcja jest lepsza, zależy od preferencji. RAC stwierdza, że oddzielenie obserwowalnego gorącego / zimnego było konieczne i że jest to podstawowa cecha frameworka, RxSwift twierdzi, że ich unifikacja jest lepsza niż separacja, znowu chodzi tylko o to, jak efekty uboczne są kontrolowane / wykonywane.
Wydaje się, że RAC 3.0 wprowadził nieoczekiwaną złożoność nad głównym celem oddzielenia obserwowalnych wartości od gorących / zimnych, jak koncepcja przerwania, rozdzielenie operatorów między 2 byty i wprowadzenie pewnych zachowań koniecznych, takich jak start
rozpoczęcie produkcji sygnałów. Dla niektórych osób te rzeczy mogą być miłe, a nawet zabójcze, dla innych mogą być niepotrzebne lub nawet niebezpieczne. Kolejną rzeczą do zapamiętania jest to, że RAC stara się jak najlepiej nadążać za konwencjami Cocoa, więc jeśli jesteś doświadczonym twórcą Cocoa, powinieneś czuć się bardziej komfortowo z nim pracować, niż z RxSwift.
Z drugiej strony RxSwift żyje ze wszystkimi wadami, takimi jak obserwowalne ciepło / zimno, ale także z dobrymi cechami Reactive Extensions. Przejście z RxJS, RxJava lub Rx.Net do RxSwift jest prostą rzeczą, wszystkie koncepcje są takie same, więc to sprawia, że znalezienie materiału jest dość interesujące, być może ten sam problem, przed którym teraz stoisz, został rozwiązany przez kogoś w RxJava i rozwiązanie można ponownie zastosować, biorąc pod uwagę platformę.
To, który należy wybrać, jest zdecydowanie kwestią preferencji, z obiektywnego punktu widzenia nie można stwierdzić, który jest lepszy. Jedynym sposobem jest zwolnienie Xcode i wypróbowanie obu z nich i wybranie tego, z którym wygodniej jest pracować. Są to 2 implementacje podobnych koncepcji, starające się osiągnąć ten sam cel: uproszczenie tworzenia oprogramowania.