ReactiveCocoa vs RxSwift - prós e contras?

256

Agora, com rapidez, o ReactiveCocoa reescreveu na versão 3.0 para o Swift

Além disso, houve outro projeto chamado RxSwift .

Gostaria de saber se as pessoas poderiam adicionar informações sobre quais são as diferenças de design / API / filosofia das duas estruturas (por favor, no espírito do SO, atenha-se às coisas verdadeiras, em vez de opiniões sobre qual é a melhor).

[Nota para os mods StackOverflow: Esta pergunta possui respostas definitivas, a resposta são as diferenças entre as duas estruturas. Eu acho que também é altamente sobre o tópico para SO]

Para começar, minha impressão inicial ao ler os ReadMe's é:

  • Como alguém familiarizado com o C # Rx "real" da microsoft, o RxSwift parece muito mais reconhecível.
  • A ReactiveCococa parece ter entrado em seu próprio espaço agora, introduzindo novas abstrações, como Signals vs SignalProducers e Lifting. Por um lado, isso parece esclarecer algumas situações (o que é um sinal Quente versus Frio), mas, por outro lado, isso parece aumentar a complexidade da estrutura.
Orion Edwards
fonte
Sua pergunta pede especificamente "opiniões". Poderia, por favor reformular? Terei prazer em retirar meu voto íntimo.
Sulthan
2
Você pode se livrar de "adicionar suas opiniões", porque as diferenças são fatos, não opiniões. Então você pode gostar ou não de alguns recursos do RAC / RxSwift, mas as diferenças são claras.
bontoJR
1
hahaha, boa jogada em relação à "note to mods"!
Ming yeow
1
Renomear pergunta: Diferença entre ReactiveCocoa e RxSwift. Eu acho que tudo se tornará "fato", e esta questão é legada.
Hqt 01/05/19
1
Até a solução começa com "Esta é uma pergunta muito boa". : |
Iulian Onofrei 01/11

Respostas:

419

Esta é uma pergunta muito boa. Comparar os dois mundos é muito difícil. Rx é uma porta do que as Extensões Reativas são em outros idiomas como C #, Java ou JS.

O cacau reativo foi inspirado pela programação reativa funcional , mas nos últimos meses, também foi apontado como inspirado pelas extensões reativas também. O resultado é uma estrutura que compartilha algumas coisas com o Rx, mas tem nomes com origens no FRP.

A primeira coisa a dizer é que nem o RAC nem o RxSwift são implementações de Programação Reativa Funcional , de acordo com a definição do conceito de Conal . A partir deste ponto, tudo pode ser reduzido à maneira como cada estrutura lida com efeitos colaterais e alguns outros componentes.

Vamos falar sobre a comunidade e as coisas meta-tech :

  • O RAC é um projeto de 3 anos de idade, nascido em Objective-C posteriormente portado para Swift (com pontes) para a versão 3.0, depois de abandonar completamente o trabalho em andamento no Objective-C.
  • O RxSwift é um projeto de alguns meses e parece ter um impulso na comunidade no momento. Uma coisa importante para o RxSwift é que ela está sob a organização ReactiveX e que todas as outras implementações estão funcionando da mesma maneira, aprender a lidar com o RxSwift tornará o trabalho com o Rx.Net, RxJava ou RxJS uma tarefa simples e apenas uma questão. da sintaxe da linguagem. Eu poderia dizer que é baseado na filosofia de aprender uma vez, aplicar em qualquer lugar .

Agora é hora do material técnico.

Entidades Produtoras / Observadoras

O RAC 3.0 possui duas entidades principais Signale SignalProducer, a primeira publica eventos independentemente de um assinante estar conectado ou não, a segunda exige startque os sinais / eventos sejam realmente produzidos. Este design foi criado para separar o conceito tedioso de observáveis ​​quentes e frios, que tem sido fonte de confusão para muitos desenvolvedores. É por isso que as diferenças podem ser reduzidas à maneira como gerenciam os efeitos colaterais .

No RxSwift, Signale SignalProducertraduz para Observable, pode parecer confuso, mas essas duas entidades são realmente a mesma coisa no mundo do Rx. Um design com Observables no RxSwift deve ser criado, considerando se estão quentes ou frios, pode parecer uma complexidade desnecessária, mas depois que você entende como eles funcionam (e novamente quente / frio / quente são os efeitos colaterais durante a inscrição / observação) ) eles podem ser domados.

Nos dois mundos, o conceito de assinatura é basicamente o mesmo, existe uma pequena diferença que o RAC introduziu e é o interruptionevento em que um Signalé descartado antes do envio do evento de conclusão. Para recapitular, ambos têm os seguintes tipos de eventos:

  • Next, para calcular o novo valor recebido
  • Error, para calcular um erro e concluir o fluxo, cancelando a inscrição de todos os observadores
  • Complete, para marcar o fluxo como concluído, cancelando a inscrição de todos os observadores

Além disso, o RAC interruptedé enviado quando um Signalé descartado antes de ser concluído corretamente ou com um erro.

Escrevendo manualmente

No RAC, Signal/ SignalProducersão entidades somente leitura, elas não podem ser gerenciadas de fora, o mesmo ocorre Observableno RxSwift. Para transformar um Signal/ SignalProducerem uma entidade gravável, você deve usar a pipe()função para retornar um item controlado manualmente. No espaço Rx, esse é um tipo diferente chamado Subject.

Se o conceito de leitura / gravação parecer desconhecido, uma boa analogia com Future/ Promisepode ser feita. A Futureé um espaço reservado somente leitura, como Signal/ SignalProducere Observable, por outro lado, a Promisepode ser preenchido manualmente, como para pipe()eSubject .

Agendadores

Essa entidade é praticamente semelhante nos dois mundos, nos mesmos conceitos, mas o RAC é somente serial; o RxSwift também apresenta agendadores simultâneos.

Composição

A composição é o principal recurso da Programação Reativa. A composição de fluxos é a essência de ambas as estruturas, no RxSwift elas também são chamadas de sequências .

Todas as entidades observáveis ​​no RxSwift são do tipo ObservableType, portanto, compomos instâncias dos Subjecte Observablecom os mesmos operadores, sem nenhuma preocupação extra.

No domínio do espaço RAC, Signale SignalProducersão 2 entidades diferentes e temos que liftem SignalProducerser capaz de compor o que é produzido com casos deSignal . As duas entidades têm seus próprios operadores; portanto, quando você precisa misturar coisas, é necessário garantir que um determinado operador esteja disponível; por outro lado, você esquece os observáveis ​​quentes / frios.

Sobre esta parte, Colin Eberhardt resumiu bem:

Observando a API atual, as operações do sinal estão focadas principalmente no evento 'next', permitindo transformar valores, pular, atrasar, combinar e observar em diferentes threads. Enquanto a API do produtor de sinal está preocupada principalmente com os eventos do ciclo de vida do sinal (concluído, erro), com operações que incluem flatMap, takeUntil e catch.

Extra

O RAC também tem o conceito de Actione Property, o primeiro é um tipo de cálculo de efeitos colaterais, principalmente relacionado à interação do usuário, o último é interessante ao observar um valor para executar uma tarefa quando o valor foi alterado. No RxSwift, as Actionconversões são novamente convertidas Observableem RxCocoauma integração bem- sucedida das primitivas Rx para iOS e Mac. Os RACs Propertypodem ser traduzidos para Variable(ouBehaviourSubject RACs ) no RxSwift.

É importante entender que Property/ Variableé a maneira como temos de conectar o mundo imperativo à natureza declarativa da Programação Reativa; portanto, às vezes, é um componente fundamental ao lidar com bibliotecas de terceiros ou funcionalidades essenciais do espaço iOS / Mac.

Conclusão

O RAC e o RxSwift são duas bestas diferentes, a primeira tem uma longa história no espaço do cacau e muitos colaboradores, a segunda é bastante jovem, mas conta com conceitos que provaram ser eficazes em outras linguagens como Java, JS ou .INTERNET. A decisão sobre o que é melhor é de preferência. O RAC afirma que a separação de quente / frio observável era necessária e esse é o principal recurso da estrutura, RxSwift diz que a unificação deles é melhor que a separação, novamente é apenas como os efeitos colaterais são gerenciados / executados.

O RAC 3.0 parece ter introduzido alguma complexidade inesperada, além do objetivo principal de separar observáveis ​​quentes / frios, como o conceito de interrupção, dividindo os operadores entre duas entidades e introduzindo um comportamento imperativo, como startcomeçar a produzir sinais. Para algumas pessoas, essas coisas podem ser uma coisa agradável de se ter ou até mesmo um recurso matador; para outras, elas podem ser apenas desnecessárias ou até perigosas. Outra coisa a lembrar é que o RAC está tentando acompanhar as convenções de cacau o máximo possível; portanto, se você é um desenvolvedor de cacau experiente, deve sentir mais confortável em trabalhar com ele do que no RxSwift.

O RxSwift, por outro lado, vive com todas as desvantagens, como observáveis ​​quentes / frios, mas também as coisas boas, das Extensões Reativas. Mover-se de RxJS, RxJava ou Rx.Net para RxSwift é uma coisa simples, todos os conceitos são os mesmos, o que torna a descoberta de material bastante interessante, talvez o mesmo problema que você está enfrentando agora, foi resolvida por alguém no RxJava e a solução pode ser reaplicado levando em consideração a plataforma.

Qual deles deve ser escolhido é definitivamente uma questão de preferência, de uma perspectiva objetiva é impossível dizer qual é o melhor. A única maneira é acionar o Xcode, experimentar os dois e escolher o que se sente mais confortável para trabalhar. São duas implementações de conceitos semelhantes, tentando alcançar o mesmo objetivo: simplificar o desenvolvimento de software.

bontoJR
fonte
24
Esta é uma ótima explicação, @ junior-b! Também vale a pena mencionar, no entanto, que o RAC codifica informações de tipo (incluindo falta de erros devido a NoError) nos próprios tipos de fluxo: Signal<T, E: ErrorType>versus Observable<T>. Isso, assim como a separação quente / frio, fornece uma quantidade maior de informações em tempo de compilação que você simplesmente não possui RxSwift.
NachoSoto
3
Olá @nachosoto, obrigado pela palavra gentil. Eu acho que a adição proposta não se encaixaria tão bem em uma comparação sobre Programação Reativa. É definitivamente uma boa adição do lado do RAC, mas para mim o RP é sobre a simplificação da programação do fluxo de dados e fatores importantes são: tratamento de erros, computação assíncrona, gerenciamento de efeitos colaterais e composição. Do ponto de vista do desenvolvedor, parece um bom recurso, para esclarecer o tipo de erro no código, não está realmente melhorando o aspecto de manipulação de erros da estrutura, essa é, obviamente, minha humilde opinião.
precisa saber é
3
Vale ressaltar que, a partir de agora, faltam tutoriais decentes sobre o RAC, no entanto, existem alguns exemplos de projetos excelentes para o RxSwift que foram decisivos para mim.
Vadim Bulavin
1
O ReactiveCocoa foi bom, até que eles introduziram funções gratuitas, SignalProducer, genéricas com Error. I aprender RxSwift e eu obter a mesma experiência ao trabalhar com RxKotlin, RxJS
onmyway133