ReactiveCocoa vs RxSwift - плюсы и минусы?

Итак, теперь с быстрым, ReactiveCocoa люди переписали его в версии 3.0 для быстрого

Кроме того, был создан еще один проект, называемый RxSwift.

Интересно, могут ли люди добавить информацию о том, каковы различия в дизайне/апи/философии двух фреймворков (пожалуйста, в духе SO, придерживайтесь вещей, которые верны, а не мнения о том, что является "лучшим", )

[Примечание для модов StackOverflow: этот вопрос имеет окончательные ответы, ответ - различия между двумя структурами. Я думаю, что он также очень по теме для SO]

Чтобы начать, мое первоначальное впечатление от чтения их ReadMe:

  • Как человек, знакомый с "реальным" С# Rx от Microsoft, RxSwift выглядит гораздо более узнаваемым.
  • ReactiveCococa, похоже, уже ушла в свое собственное пространство, представив новые абстракции, такие как Signals vs SignalProducers и Lifting. С одной стороны, это, по-видимому, разъясняет некоторые ситуации (что такое сигнал Hot vs Cold), но, с другой стороны, это, по-видимому, увеличивает сложность структуры LOT

Ответ 1

Это очень хороший вопрос. Сравнение двух миров очень сложно. Rx - это порт того, что Reactive Extensions находится на других языках, таких как С#, Java или JS.

Реактивный Cocoa был вдохновлен функционально-реактивным программированием, но в последние месяцы также был отмечен как вдохновленный реактивными расширениями. Результатом является структура, которая разделяет некоторые вещи с Rx, но имеет имена с источником в FRP.

Первое, что нужно сказать, - это то, что ни RAC, ни RxSwift не являются реализациями функционального реактивного программирования, согласно определению конуса концепции. С этого момента все можно свести к тому, как каждая структура обрабатывает побочные эффекты и несколько других компонентов.

Расскажите о сообществе и метатехнике:

  • RAC - это трехлетний проект, родившийся в Objective-C, позже перенесенный в Swift (с мостами) для версии 3.0 после полного отказа от текущей работы над Objective-C.
  • RxSwift - это проект на несколько месяцев, и, похоже, сейчас у него есть импульс в сообществе. Для RxSwift важна то, что находится в ReactiveX и что все другие реализации работают одинаково, изучая, как сделка с RxSwift сделает работу с Rx.Net, RxJava или RxJS простой задачей и просто вопросом синтаксиса языка. Я мог бы сказать, что это основано на том, что философия учится один раз, применяйте повсюду.

Теперь настало время для техник.

Производящие/наблюдающие объекты

RAC 3.0 имеет 2 основных объекта, Signal и SignalProducer, первый публикует события независимо от того, подключен ли абонент или нет, второй требует start для фактического получения сигналов/событий. Этот дизайн был создан, чтобы отделить утомительную концепцию горячих и холодных наблюдаемых, которая стала источником путаницы для многих разработчиков. Вот почему различия могут быть уменьшены до того, как они управляют побочными эффектами.

В RxSwift Signal и SignalProducer переводится на Observable, это может показаться запутанным, но эти 2 сущности на самом деле одно и то же в мире Rx. Дизайн с Observable в RxSwift должен быть создан, учитывая, что они горячие или холодные, это может звучать как ненужная сложность, но как только вы поняли, как они работают (и снова горячий/холодный/теплый - это только побочные эффекты при подписке/наблюдение) их можно приручить.

В обоих мирах концепция подписки в основном одна и та же, существует одна небольшая разница, которую RAC представляет и является событием interruption, когда Signal удаляется до того, как событие завершения было отправлено. Напомним, что они имеют следующие события:

  • Next, чтобы вычислить новое полученное значение
  • Error, чтобы вычислить ошибку и завершить поток, отменив подписку на всех наблюдателей
  • Complete, чтобы отметить поток как завершенную отмену подписки на всех наблюдателей

Кроме того, RAC имеет interrupted, который отправляется, когда Signal располагается до завершения либо с ошибкой, либо с ошибкой.

Вручную писать

В RAC, Signal/SignalProducer являются объектами только для чтения, они не могут управляться извне, то же самое для Observable в RxSwift. Чтобы превратить Signal/SignalProducer в объект, способный к записи, вы должны использовать функцию pipe() для возврата элемента, управляемого вручную. В пространстве Rx это другой тип, называемый Subject.

Если концепция чтения/записи звучит незнакомо, можно сделать приятную аналогию с Future/Promise. A Future является заполнителем только для чтения, например Signal/SignalProducer и Observable, а Promise может выполняться вручную, например, для pipe() и Subject.

Планировщики

Этот объект очень похож в обоих мирах, те же концепции, но RAC является последовательным, вместо этого RxSwift имеет также параллельные планировщики.

Состав

Состав - ключевая особенность реактивного программирования. Составляющие потоки суть сущности обеих фреймворков, в RxSwift их также называют последовательностями.

Все наблюдаемые объекты в RxSwift имеют тип ObservableType, поэтому мы создаем экземпляры Subject и Observable с теми же операторами без каких-либо дополнительных проблем.

В RAC-пространстве Signal и SignalProducer являются 2 разными объектами, и мы должны lift на SignalProducer, чтобы иметь возможность составлять то, что создается с экземплярами Signal. У двух сущностей есть свои собственные операторы, поэтому, когда вам нужно смешивать вещи, вы должны убедиться, что есть определенный оператор, с другой стороны вы забыли о горячих/холодных наблюдаемых.

Об этой части Colin Eberhardt подвел итог:

Глядя на текущий API, операции с сигналами в основном сосредоточены на "следующем событии", что позволяет вам преобразовывать значения, пропускать, задерживать, комбинировать и наблюдать на разных потоках. В то время как API-провайдер сигналов в основном связан с событиями жизненного цикла сигнала (завершенными, ошибками), с операциями, включая then flatMap, takeUntil и catch.

Дополнительные

RAC также имеет концепцию Action и Property, первая - это тип для вычисления побочных эффектов, в основном связанных с взаимодействием с пользователем, последний интересен при наблюдении значения для выполнения задачи, когда значение изменилось, В RxSwift Action снова переводится в Observable, это хорошо показано в RxCocoa, интеграция Rx-примитивов для iOS и Mac. RAC Property может быть переведен в Variable (или BehaviourSubject) в RxSwift.

Важно понимать, что Property/Variable - это то, как мы должны свести императивный мир к декларативному характеру реактивного программирования, поэтому иногда это фундаментальный компонент при работе с сторонними библиотеками или основными функциональными возможностями iOS/Mac.

Заключение

RAC и RxSwift - это 2 полных разных зверя, первый имеет длинную историю в пространстве Cocoa и много участников, последний довольно молод, но полагается на концепции, которые оказались эффективными на других языках как Java, JS или .NET. Решение о том, что лучше, предпочтительнее. RAC заявляет, что разделение горячей/холодной наблюдаемой было необходимым, и это основная особенность структуры, RxSwift говорит, что объединение их лучше, чем разделение, опять же это просто о том, как управлять/выполнять побочные эффекты.

RAC 3.0, похоже, внедрил некоторую неожиданную сложность поверх главной цели разделения горячих/холодных наблюдаемых, таких как концепция прерывания, разделение операторов между двумя объектами и введение некоторого императивного поведения, такого как start, для начала генерации сигналов. Для некоторых людей это может быть хорошей вещью, чтобы иметь или даже функцию убийцы, для некоторых других они могут быть просто лишними или даже опасными. Еще одна вещь, которую следует помнить, заключается в том, что RAC пытается как можно больше поддерживать соглашения Cocoa, поэтому, если вы опытный Cocoa Dev, вам следует чувствовать себя более комфортно, чтобы работать с ним чем RxSwift.

RxSwift, с другой стороны, живет со всеми минусами, такими как горячие/холодные наблюдаемые, но также и хорошие вещи из Reactive Extensions. Переход от RxJS, RxJava или Rx.Net к RxSwift - это просто, все концепции одинаковы, поэтому это делает поиск материала довольно интересным, может быть, с той же проблемой, с которой вы сейчас сталкиваетесь, был решен кем-то в RxJava и решением может быть повторно применена с учетом платформы.

Кто должен быть выбран, определенно является вопросом предпочтения, с объективной точки зрения невозможно сказать, какой из них лучше. Единственный способ - запустить Xcode и попробовать оба из них и выбрать тот, с которым вам удобнее работать. Это две реализации аналогичных концепций, стремящихся достичь той же цели: упрощение разработки программного обеспечения.