Подтвердить что ты не робот

Если IObservable будет предпочтительнее событий при экспонировании уведомлений в библиотеке, ориентированной на .NET 4+

У меня есть библиотека .NET, которая, как часть объектной модели, будет излучать уведомления о некоторых событиях.

Мне кажется, что основными плюсами событий являются доступность для новичков (и простота в определенных контекстах потребления) с основным отрицательным состоянием в том, что они не скомпонован и, следовательно, сразу же принудительно вставляются в Observable.FromEvent *, если вы хотите сделать что-нибудь интересное, не пиши кусок кода.

Характер решаемой проблемы таков, что трафик событий не будет особенно частым или объемным (он определенно не кричит RX), но, безусловно, нет необходимости поддерживать версии .NET до 4.0 [и, следовательно, я может использовать встроенный интерфейс IObservable в System.Reactive без каких-либо существенных зависимостей от потребителей]. Я заинтересован в <общих > рекомендациях некоторых конкретных конкретных предпосылках, чтобы предпочесть IObservables более event с точки зрения дизайна API, хотя - независимо от того, где мой конкретный случай может стоять на event - IObservable.

Итак, вопрос:

Есть ли что-то конкретное, я делаю значительно сложнее или проблематично для потребителей API, если я иду с самой простой вещью и выставляю event вместо IObservable

Или, пересчитано: помимо того, что пользователь должен сделать Observable.FromEvent *, чтобы иметь возможность составлять события, действительно нет никакой причины предпочитать IObservable над event при экспонировании уведомления в API?

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


NB, затронутый в комментариях с @Adam Houldsworth, меня интересуют конкретные вещи по поверхности API библиотеки .NET 4+, а не обзор мнений относительно того, что представляет собой лучшую "архитектуру по умолчанию" для наше время:)

NB этот вопрос был затронут в IObserver и IObservable в С# для Observer vs Delegates, Events и IObservable vs Plain События или почему я должен использовать IObservable?. Аспект вопроса, который я задаю, не рассматривался ни в одном из ответов из-за нарушений СРП. Еще один слегка перекрывающий вопрос - Преимущества .NET Rx над классическими событиями?. (Использование IObservable вместо событий) [Использование IObservable вместо событий относится к той же категории.

4b9b3361

Ответ 1

В комментариях этого ответа OP уточнил свой вопрос как:

[Это действительно действительно случай, когда каждое событие может всегда быть адаптированным как IObservable?

На этот вопрос ответ в основном да - но с некоторыми оговорками. Также обратите внимание, что обратное неверно - см. Раздел об обратном преобразовании и заключение по причинам, почему наблюдаемые могут быть предпочтительнее классических событий из-за дополнительного значения, которое они могут передать.

Для строгой трансляции все, что нам нужно сделать, это сопоставить событие, которое должно включать отправителя, а также аргументы, - на вызов OnNext. Этот вспомогательный метод Observable.FromEventPattern хорошо справляется с перегрузкой, возвращающей IObservable<EventPattern<T>>, предоставляя как объект-отправитель, так и EventArgs.

Предостережения

Вспомните грамматику Rx. Это можно выразить в форме С# 5.0 Language Specification (это документ с текстом, см. раздел 1.6.7.4) и . Рекомендации по дизайну NET Framework: дизайн событий имеют мало что сказать о поведении события. Спектр наблюдает, что:

Понятие поднятия события точно эквивалентно вызову делегата, представленного мероприятием, - поэтому нет специального языка конструкции для создания событий.

В разделе С# Programming Guide: Events говорится:

Когда событие имеет несколько подписчиков, активируются обработчики событий синхронно при возникновении события. Чтобы вызвать события асинхронно, см. Асинхронный вызов синхронных методов.

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

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

Это контрастирует с наблюдаемыми, где оно явно указано в Rx Design Guidelines, что мы должны:

4,2. Предположим, что экземпляры наблюдателя вызывают сериализованным способом

Обратите внимание, что этот оператор относится только к точке зрения отдельного экземпляра абонента и ничего не говорит о событиях, отправляемых одновременно между экземплярами (что на самом деле очень распространено в Rx).

Итак, две вещи:

  • В то время как OnNext фиксирует идею события, возможно, классическое событие .NET может нарушить грамматику Rx путем одновременного вызова событий.
  • Общим для чистых Rx Observables является разная семантика вокруг доставки событий под нагрузкой, поскольку обратное давление обычно обрабатывается для каждого абонента, а не для каждого события.

Пока вы не поднимаете события одновременно в своем API, и вам не нужна семантика обратного давления, тогда перевод на наблюдаемый интерфейс с помощью механизма, такого как Rx Observable.FromEvent, будет очень хорошим.

Обратное преобразование

В обратном преобразовании обратите внимание, что OnError и OnCompleted не имеют аналога в классических событиях .NET, поэтому невозможно сделать обратное отображение без каких-либо дополнительных механизмов и согласованного использования.

Например, можно перевести OnError и OnCompleted в дополнительные события, но это определенно выходит за рамки классической территории событий. Кроме того, для разных обработчиков потребуется некоторый очень неудобный механизм синхронизации; в Rx вполне возможно, что один абонент получит OnCompleted, в то время как другой все еще принимает события OnNext - это намного сложнее осуществить в классическом преобразовании событий .NET.

Ошибки

Рассмотрение поведения в случаях ошибок: важно различать ошибку в источнике события от одного в обработчиках/подписчиках. OnError есть дело с первым, в последнем случае оба классических события и Rx просто (и правильно) взрываются. Этот аспект ошибок хорошо переносится в любом направлении.

Заключение

Классические события .NET и Observables не изоморфны. Вы можете легко перевести с событий на наблюдаемые, пока вы придерживаетесь обычных шаблонов использования. Возможно, ваш API требует дополнительной семантики наблюдаемых данных, которые не так легко смоделированы с событиями .NET, и поэтому имеет смысл идти только Observable - но это конкретное соображение, а не общее, а другое - дизайн чем технический.

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

Ответ 2

Я много читал о реактивных расширениях, прежде чем, наконец, погрузился в мой палец, и после некоторых грубых запусков я нашел их действительно интересными и полезными.

Расширение Observables имеет этот прекрасный необязательный параметр, в котором вы можете передать свой собственный менеджер времени, эффективно позволяя манипулировать временем. В моем случае это очень помогло с тех пор, как я занимался какой-то временной работой (проверяйте этот веб-сервис каждые десять минут, отправляйте по электронной почте в минуту и ​​т.д.), И это заставляло испытывать легкий ветерок. Я бы подключил TestScheduler в тестируемом компоненте и мгновенно имитировал один день событий.

Итак, если у вас есть некоторые рабочие процессы в вашей библиотеке, где время играет роль в оркестровке, я бы рекомендовал использовать Observables в качестве вывода.

Однако, если вы просто поднимаете события в прямых ответах на пользовательские входы, я не думаю, что это стоит дополнительной сложности для ваших пользователей. Как вы заметили, они могут поместить событие в свое собственное Наблюдаемое, если необходимо.

Вы могли бы получить свой торт и съесть его, хотя это означало бы большую работу; предложите фасад, который превратит вашу библиотеку событий в систему, поддерживаемую наблюдателем, создав "Наблюдаемый" из ваших событий. Или сделать это по-другому: иметь факультативный фасад, который поддается наблюдению и поднять классическое событие при срабатывании.

По моему мнению, существует нетривиальный технический шаг, который следует предпринять при работе с реактивными расширениями, и в этом случае может произойти то, что ваши потребители API будут наиболее удобными при использовании

Ответ 3

IObservable - это IEnumerable событий, поэтому единственный вопрос здесь, как вы думаете, IObservable станет стандартом, так как IEnumerable теперь так да, его предпочтительнее, если вы считаете его просто проходящим по веществу, которое в будущем будет использоваться вместо event.

В большинстве случаев IObservable лучше, чем event, но я лично думаю, что я забуду использовать его как его не очень часто используемое, и когда придет время, я забуду об этом.

Я знаю, что мой ответ не очень помогает, но только время покажет, станет ли RX стандартом, я думаю, что у него хорошие шансы.

[EDIT] Чтобы сделать его более конкретным.

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

Как Adam Houldsworth сказал, что можно легко изменить на другую, чтобы не иметь другого отличия.

Ответ 4

Чтобы задать свой основной вопрос:

Нет, они не должны быть предпочтительными на том основании, что они существуют в .NET 4 и доступны для использования. Предпочтение зависит от предполагаемого использования, поэтому предпочтение отдается необоснованному.

Тем не менее, я бы склонялся к ним как к альтернативной модели традиционным событиям С#.

Как я уже прокомментировал этот вопрос, есть много дополнительных преимуществ для подхода к API с IObservable, не в последнюю очередь из которого является внешняя поддержка и диапазон выбора, доступный конечному потребителю.

Чтобы решить свой внутренний вопрос:

Я полагаю, что между экспонированием событий или IObserable в вашем API будет немного затруднений, поскольку в обоих случаях есть путь к одному из другого. Это наложило бы слой поверх вашего API, но на самом деле это слой, который вы также можете отпустить.

Мое мнение, что выбор одного из них не будет частью решающей причины, по которой кто-то решит использовать или не использовать ваш API.

Чтобы ответить на ваш повторно заявленный вопрос:

Причина в том, почему в первую очередь есть Observable.FromEvent:-) IObservable получает поддержку во многих местах .NET для реактивного программирования и является частью многих популярных библиотек (Rx, Ix, ReactiveUI), а также хорошо взаимодействует с LINQ и IEnumerable и далее в TPL и TPL DataFlow.

Пример не-Rx наблюдаемого шаблона, поэтому специально не было IObservable для приложений XAML ObservableCollection.