Что в приведенном псевдокоде Вам непонятно?
КЛ>>Я писал о внешних источниках — не о внутренних. G>А чем они хуже\лучше внутренних?
Тем, что они доступны в любой момент — под них не надо подстраиваться.
КЛ>>>>(1) либо запустить Принимальщик Решений в отдельном потоке со своей частотой, которая не зависит от частоты поступления событий; G>>>Плохо, потому что частоты входящих событий не фиксированы. КЛ>>Чем плохо? G>Тем что в среднем неэффективно получится, или реакция будет запаздывать, или ресурсы прожигаться будут. Так или иначе масштабируемость ухудшится.
Не думаю. Наоборот, основной цикл программы будет работать с той частотой, которая нам будет нужна, и не будет зависеть от перепадов нагрузки. Поток не зависнет, если по какой-либо причине количество входящих запросов вдруг резко возрастет. В целом, решение получается достаточно надежным и масштабируемым.
КЛ>>Понимаю, что это может сократить код при реализации, но не понимаю, как это влияет на проектирование и на выработку концептуального решения? G>Потому что вводится новая абстракция (первоклассная сущность) — поток событий. G>Примерно также при ФП дизайн получается не такой же как при ООП.
Не вижу причин, по которым "поток событий" нельзя описать без привязки с определенной технологии.
Абстрактно: Есть события А, Б и В, которые приходят с разной частотой.
Поток событий делается так: При поступлении каждое событие запоминается в некотором буфере. Далее — если пришло событие А, то берем Б и В из буфера и передаем на обработку. Если пришло Б, то берем А и В и т.д.
Технология тут не при чем. Фактически, получается то же самое, что я и описал при помощи таблиц.
G>Ну мы ведь не об обычных приложениях говорим. Когда начинают возится с асинхронным IO, то рассчитывают на большую нагрузку. И тС привел пример приложений, в которых время реакции очень важно.
На мой взгляд, лучше придерживаться поставленной задачи — иначе уйдем в дебри.
Понятно все, непонятно как это заставить работать эффективно. Нужен язык вроде Erlang с "зелеными" потоками, в других языках придется "зелень" вручную создавать.
КЛ>>>Я писал о внешних источниках — не о внутренних. G>>А чем они хуже\лучше внутренних? КЛ>Тем, что они доступны в любой момент — под них не надо подстраиваться.
Проблемы есть пока считаешь эти потоки разными, как только появляется абстракция, которая позволяет не "подстраиваться" сразу проблемы исчезают.
КЛ>>>>>(1) либо запустить Принимальщик Решений в отдельном потоке со своей частотой, которая не зависит от частоты поступления событий; G>>>>Плохо, потому что частоты входящих событий не фиксированы. КЛ>>>Чем плохо? G>>Тем что в среднем неэффективно получится, или реакция будет запаздывать, или ресурсы прожигаться будут. Так или иначе масштабируемость ухудшится. КЛ>Не думаю. Наоборот, основной цикл программы будет работать с той частотой, которая нам будет нужна, и не будет зависеть от перепадов нагрузки.
Не понял, выделенное за счет чего будет достигаться? Куда дополнительная нагрузка рассеиваться будет?
КЛ>Поток не зависнет, если по какой-либо причине количество входящих запросов вдруг резко возрастет. В целом, решение получается достаточно надежным и масштабируемым.
Ок, топикстартер приводил здесь код, я его написал в варианте с Rx. Напиши его в своем варианте, просто сравним результаты под нагрузкой.
КЛ>>>Понимаю, что это может сократить код при реализации, но не понимаю, как это влияет на проектирование и на выработку концептуального решения? G>>Потому что вводится новая абстракция (первоклассная сущность) — поток событий. G>>Примерно также при ФП дизайн получается не такой же как при ООП. КЛ>Не вижу причин, по которым "поток событий" нельзя описать без привязки с определенной технологии.
Таких причин собственно и нет. Rx уже портировали на JS и собираются портировать на С++. Сами интерфейсы, описывающие абстракции потоков событий, очень простые. Буквально два интерфейса с 1 и 3 методами. Сила Rx не столько в количестве написанного кода, сколько в том что этот код опирается на строгую математику.
КЛ>Абстрактно: Есть события А, Б и В, которые приходят с разной частотой. КЛ>Поток событий делается так: При поступлении каждое событие запоминается в некотором буфере. Далее — если пришло событие А, то берем Б и В из буфера и передаем на обработку. Если пришло Б, то берем А и В и т.д.
Меня собственно интересует реализация этой логики "если.., то.." не получился ли куча ифов, от которых старались уйти?
КЛ>Технология тут не при чем. Фактически, получается то же самое, что я и описал при помощи таблиц.
Именно технология причем. Цель известна, ТС привел код. Проблемы также известны — необходиомсть хранить состояние. Я варианты реализации уже привел, их буквально 3 штуки. Теперь можем попробовать на реальном коде оценить достоинства и недостатки каждого из них.
G>>Ну мы ведь не об обычных приложениях говорим. Когда начинают возится с асинхронным IO, то рассчитывают на большую нагрузку. И тС привел пример приложений, в которых время реакции очень важно. КЛ>На мой взгляд, лучше придерживаться поставленной задачи — иначе уйдем в дебри.
Ну так поставленная задача — написать торгового бота, обычно серьезные торговые стратегии опрерируют кучей событий и работают под большой нагрузкой, поэтому нужна масштабируемость (то есть минимальный порядок роста потребляемых ресурсов при возрастании количества входящих сообщений).
Re[18]: Good practice по алгоритмизации в условиях асинхронн
Здравствуйте, gandjustas, Вы писали:
КЛ>>Что в приведенном псевдокоде Вам непонятно? G>Понятно все, непонятно как это заставить работать эффективно. Нужен язык вроде Erlang с "зелеными" потоками, в других языках придется "зелень" вручную создавать.
Трудно комментировать оценки. По приведенному коду есть какой-нибудь осмысленный вопрос?
КЛ>>Не думаю. Наоборот, основной цикл программы будет работать с той частотой, которая нам будет нужна, и не будет зависеть от перепадов нагрузки. G>Не понял, выделенное за счет чего будет достигаться? Куда дополнительная нагрузка рассеиваться будет?
За счет того, что основной цикл будет зависеть от частоты поступающих сообщений. А дополнительная нагрузка будет "рассеиваться":
(1) либо сама собой, когда минует пиковая нагрузка;
(2) либо при помощи потери устаревших сообщений;
(3) либо путем распределения нагрузки между доп. серверами.
В последнем случае у нас будет не один обработчик бизнес-логики, а несколько.
КЛ>>Поток не зависнет, если по какой-либо причине количество входящих запросов вдруг резко возрастет. В целом, решение получается достаточно надежным и масштабируемым. G>Ок, топикстартер приводил здесь код, я его написал в варианте с Rx. Напиши его в своем варианте, просто сравним результаты под нагрузкой.
У меня нет особого желания переубеждать тебя в чем-то. Высказать свои аргументы я могу, а вот тратить несколько часов (а может и дней) своего времени на написание полностью работающего и отлаженного кода на С++ у меня, честно говоря, нет желания. Но если ты все-таки хочешь убедиться в том, чей вариант будет работать лучше, то предлагаю тебе реализовать оба варианта (и свой, и мой) самому, самостоятельно провести тестирование и сообщить нам о результатах. И мне, и коллегам, полагаю, это будет интересно.
КЛ>>Абстрактно: Есть события А, Б и В, которые приходят с разной частотой. КЛ>>Поток событий делается так: При поступлении каждое событие запоминается в некотором буфере. Далее — если пришло событие А, то берем Б и В из буфера и передаем на обработку. Если пришло Б, то берем А и В и т.д. G>Меня собственно интересует реализация этой логики "если.., то.." не получился ли куча ифов, от которых старались уйти?
Нет, не получится. По крайней мере, не будет вложенности условий, и код будет содержать один оператор if.
КЛ>>Технология тут не при чем. Фактически, получается то же самое, что я и описал при помощи таблиц. G>Именно технология причем. Цель известна, ТС привел код. Проблемы также известны — необходиомсть хранить состояние. Я варианты реализации уже привел, их буквально 3 штуки. Теперь можем попробовать на реальном коде оценить достоинства и недостатки каждого из них.
Технологии постоянно меняются + зависят от платформы и языка. А решая задачу без привязки к технологиям, можно очень легко переносить решения с платформы на платформу. Фактически, благодаря такому подходу мне и моим бывшим коллегам было нетрудно портировать навигационную систему с платформы на платформу, например, с Windows Mobile под Symbian.
КЛ>>На мой взгляд, лучше придерживаться поставленной задачи — иначе уйдем в дебри. G>Ну так поставленная задача — написать торгового бота, обычно серьезные торговые стратегии опрерируют кучей событий и работают под большой нагрузкой, поэтому нужна масштабируемость (то есть минимальный порядок роста потребляемых ресурсов при возрастании количества входящих сообщений).
Это уже твое предположение (пусть и имеющее некоторые основания). В исходной постановке об этом не было ни слова.
Здравствуйте, Кирилл Лебедев, Вы писали:
КЛ>Здравствуйте, gandjustas, Вы писали:
КЛ>>>Что в приведенном псевдокоде Вам непонятно? G>>Понятно все, непонятно как это заставить работать эффективно. Нужен язык вроде Erlang с "зелеными" потоками, в других языках придется "зелень" вручную создавать.
КЛ>Трудно комментировать оценки. По приведенному коду есть какой-нибудь осмысленный вопрос?
КЛ>>>Не думаю. Наоборот, основной цикл программы будет работать с той частотой, которая нам будет нужна, и не будет зависеть от перепадов нагрузки. G>>Не понял, выделенное за счет чего будет достигаться? Куда дополнительная нагрузка рассеиваться будет? КЛ>За счет того, что основной цикл будет зависеть от частоты поступающих сообщений. А дополнительная нагрузка будет "рассеиваться":
КЛ>(1) либо сама собой, когда минует пиковая нагрузка;
Она не минутет. Для торговых систем она в среднем стабильна.
КЛ>(2) либо при помощи потери устаревших сообщений;
Такое вообще категорически нельзя делать. Торговые системы близки к реалтайму, большинство сообщений должны быть обработаны.
КЛ>>>Поток не зависнет, если по какой-либо причине количество входящих запросов вдруг резко возрастет. В целом, решение получается достаточно надежным и масштабируемым. G>>Ок, топикстартер приводил здесь код, я его написал в варианте с Rx. Напиши его в своем варианте, просто сравним результаты под нагрузкой.
КЛ>У меня нет особого желания переубеждать тебя в чем-то. Высказать свои аргументы я могу, а вот тратить несколько часов (а может и дней) своего времени на написание полностью работающего и отлаженного кода на С++ у меня, честно говоря, нет желания. Но если ты все-таки хочешь убедиться в том, чей вариант будет работать лучше, то предлагаю тебе реализовать оба варианта (и свой, и мой) самому, самостоятельно провести тестирование и сообщить нам о результатах. И мне, и коллегам, полагаю, это будет интересно.
ТС привел код, я приводил свой варинат. Писать агенты у меня нет желания.
Кроме того я до сих пор не понимаю как будут обрабатываться события и как о них будет узнавать обработчик БЛ.
КЛ>>>Абстрактно: Есть события А, Б и В, которые приходят с разной частотой. КЛ>>>Поток событий делается так: При поступлении каждое событие запоминается в некотором буфере. Далее — если пришло событие А, то берем Б и В из буфера и передаем на обработку. Если пришло Б, то берем А и В и т.д. G>>Меня собственно интересует реализация этой логики "если.., то.." не получился ли куча ифов, от которых старались уйти? КЛ>Нет, не получится. По крайней мере, не будет вложенности условий, и код будет содержать один оператор if.
Те псевдокод такой
Если пришло А
{
Взять Б.
В зависимости от (А,Б) выполнить действие (тоже if)
}
Если пришло Б
{
Взять А.
В зависимости от (А,Б) выполнить действие (тоже if).
}
В итоге два ифа, как и у ТС. Также получится два ифа если делать явный автомат.
Что выигрываем?
КЛ>>>Технология тут не при чем. Фактически, получается то же самое, что я и описал при помощи таблиц. G>>Именно технология причем. Цель известна, ТС привел код. Проблемы также известны — необходиомсть хранить состояние. Я варианты реализации уже привел, их буквально 3 штуки. Теперь можем попробовать на реальном коде оценить достоинства и недостатки каждого из них.
КЛ>Технологии постоянно меняются + зависят от платформы и языка. А решая задачу без привязки к технологиям, можно очень легко переносить решения с платформы на платформу. Фактически, благодаря такому подходу мне и моим бывшим коллегам было нетрудно портировать навигационную систему с платформы на платформу, например, с Windows Mobile под Symbian.
Решение всегда зависит от языка и технологий. Например код на функциональном языке всегда не поход на код на императивном языке.
Более частный пример: отсутствие yield в C++ не позволит эффективно писать итератор, который позволяет выполнять линейный код работать асинхронно.
Другой частный пример: в Silverlight\js все взаимодействие с внешним миром асинхронно, поэтому любителям писать синхронный код надо напрягаться с передачей контекста от места вызова до места обработки.
Всегда можно проектировать абстрактное решение абстрактной задачи, но в итоге в коде оно обычно получается не такое как хотелось. Я вот например до сих пор не пойму как будет делаться обработка сообщений в твоем варианте.
КЛ>>>На мой взгляд, лучше придерживаться поставленной задачи — иначе уйдем в дебри. G>>Ну так поставленная задача — написать торгового бота, обычно серьезные торговые стратегии опрерируют кучей событий и работают под большой нагрузкой, поэтому нужна масштабируемость (то есть минимальный порядок роста потребляемых ресурсов при возрастании количества входящих сообщений). КЛ>Это уже твое предположение (пусть и имеющее некоторые основания). В исходной постановке об этом не было ни слова.
Дык топикстартер привел конкретный код.
Re[20]: Good practice по алгоритмизации в условиях асинхронн
Здравствуйте, gandjustas, Вы писали:
КЛ>>(1) либо сама собой, когда минует пиковая нагрузка; G>Она не минутет. Для торговых систем она в среднем стабильна.
Тогда и не будет проблем с производительностью.
G>ТС привел код, я приводил свой варинат. Писать агенты у меня нет желания. G>Кроме того я до сих пор не понимаю как будут обрабатываться события и как о них будет узнавать обработчик БЛ.
Обработчик БЛ берет данные из таблиц (их описание см. здесь
). Он может "тупо" раз в определенное время "просыпаться", выполнять БЛ, а затем — "засыпать". Но можно его "пробуждение" приурочивать и к биржевому тику, как я писал выше.
Собственно говоря, об этом я уже писал выше не один раз.
G>Те псевдокод такой
G>
G>Если пришло А
G>{
G> Взять Б.
G> В зависимости от (А,Б) выполнить действие (тоже if)
G>}
G>Если пришло Б
G>{
G> Взять А.
G> В зависимости от (А,Б) выполнить действие (тоже if).
G>}
G>
G>В итоге два ифа, как и у ТС. Также получится два ифа если делать явный автомат. G>Что выигрываем?
if (A)
{
if (B)
{
if (!C)
do1();
do2();
}
else
{
if (C)
do1();
else
do3();
do4();
}
}
else
{
if (B)
{
if (!C)
do1();
do5();
}
else
{
if (C)
do1();
else
do6();
do2();
}
}
Чтобы избавиться от ветвистости, нужно выполнить такой алгоритм:
Шаг 1.Сгруппировать условия по действиям.
Т.е. к каждой функции приписать условия, при которых она выполняется, индивидуально.
Получится:
if (A && B && !C || A && !B && C || !A && B && !C || !A && !B && C)
do1();
if (!A && !B && !C)
do6();
if (A && B || !A && !B)
do2();
if (A && !B && !C)
do3();
if (A && !B)
do4();
if (!A && B)
do5();
Шаг 2. Упростить логические выражения.
Получим:
if (B != С)
do1();
if (!A && !B && !C)
do6();
if (A == B)
do2();
if (A && !B && !C)
do3();
if (A && !B)
do4();
if (!A && B)
do5();
Здравствуйте, Кирилл Лебедев, Вы писали:
КЛ>Здравствуйте, gandjustas, Вы писали:
КЛ>>>(1) либо сама собой, когда минует пиковая нагрузка; G>>Она не минутет. Для торговых систем она в среднем стабильна. КЛ>Тогда и не будет проблем с производительностью.
Проблемы с производительность для торговых систем тоже стабильны
G>>ТС привел код, я приводил свой варинат. Писать агенты у меня нет желания. G>>Кроме того я до сих пор не понимаю как будут обрабатываться события и как о них будет узнавать обработчик БЛ.
КЛ>Обработчик БЛ берет данные из таблиц (их описание см. здесь
). Он может "тупо" раз в определенное время "просыпаться", выполнять БЛ, а затем — "засыпать". Но можно его "пробуждение" приурочивать и к биржевому тику, как я писал выше. КЛ>Собственно говоря, об этом я уже писал выше не один раз.
Ага, а теперь сами события. Как они будут попадать в таблицы? (как понимаю это будут очереди на самом деле, терять то нельзя).
G>>Те псевдокод такой
G>>
G>>Если пришло А
G>>{
G>> Взять Б.
G>> В зависимости от (А,Б) выполнить действие (тоже if)
G>>}
G>>Если пришло Б
G>>{
G>> Взять А.
G>> В зависимости от (А,Б) выполнить действие (тоже if).
G>>}
G>>
G>>В итоге два ифа, как и у ТС. Также получится два ифа если делать явный автомат. G>>Что выигрываем?
КЛ>Нет, код будет совсем другой. Выше
КЛ>Чтобы избавиться от ветвистости, нужно выполнить такой алгоритм:
КЛ>Шаг 1.Сгруппировать условия по действиям. КЛ>Т.е. к каждой функции приписать условия, при которых она выполняется, индивидуально.
КЛ>Получится:
КЛ>
КЛ>if (A && B && !C || A && !B && C || !A && B && !C || !A && !B && C)
КЛ> do1();
КЛ>if (!A && !B && !C)
КЛ> do6();
КЛ>if (A && B || !A && !B)
КЛ> do2();
КЛ>if (A && !B && !C)
КЛ> do3();
КЛ>if (A && !B)
КЛ> do4();
КЛ>if (!A && B)
КЛ> do5();
КЛ>
КЛ>if (B != С)
КЛ> do1();
КЛ>if (!A && !B && !C)
КЛ> do6();
КЛ>if (A == B)
КЛ> do2();
КЛ>if (A && !B && !C)
КЛ> do3();
КЛ>if (A && !B)
КЛ> do4();
КЛ>if (!A && B)
КЛ> do5();
КЛ>
КЛ>Теперь стало понятнее?
Конечно, это чисто механическое действие, но ТС говорил вообще-то о другом. Я немного знаком с асинхронным программированием и знаю как громоздко выглядит нелинейный асинхронный код. Тем не менее все сводится к автомату, который реализуется ифами двух уровней (а может и одним — селектором верхнего уровня служит само событие).
А вот выкрутить в обратную сторону, как ты предлагаешь, довольно проблематично. Условие "наступило событие А текущее состояние 1 или наступило событие Б и текущее событие 2" простым способом не запишешь. Потому что событие — это push, а проверка в ифе — pull. Вот и приходится платить довольно высокую цену — создавать очереди, плодить потоки итп, только чтобы из полутора вложенных ифов получить один. Это не только хуже работает, но и сложнее сопровождается.
Re[29]: Good practice по алгоритмизации в условиях асинхронн
Здравствуйте, Undying, Вы писали:
U>Что значит асинхронно? В смысле в другом потоке? Ну так поставь таску на чтение файла в другой поток, а не в основной и будет тебе счастье.
налицо трагическое непонимание. Нет никакого "другого потока". В IOCP чтение выполняет не поток, а, грубо говоря, контроллер ввода-вывода. Именно в этом принципиальная разница. Тратить мегабайт стека только на то, чтобы он спал в ожидании контроллера — бессмысленное расточительство. С биржей всё будет ещё хуже: скажем, три тысячи отслеживаемых тикеров просто не влезут в 32хразрядное адресное пространство, если каждому выделять свой поток. Не говоря уже о том, что накладные расходы на пробуждение такого потока тоже весьма отличны от нуля.
Код, построенный на основе IOCP, может одновременно ждать сотни тысяч тикеров без заметного роста нагрузки на CPU и память. А это важно — меньше шансов попасть в своп, из которого долго подниматься при приходе долгожданного события.
При этом собственно время обработки события пренебрежимо мало — процессору достаточно наносекунд, чтобы выполнить все вычисления и принять торговое решение.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Good practice по алгоритмизации в условиях асинхронн
Здравствуйте, Undying, Вы писали:
U>А асинхронная операция в ОС она магическая или как? Ни потоков, ни процессорного времени не использует?
Совершенно верно. Она магическая. Зачем, к примеру, тратить процессорное время и/или потоки на ожидание приезда пакета в сетевую карту? Там внутри достаточно оборудования, чтобы всё сделать без нас.
Вот когда данные приехали, можно и сообщить в пользовательский код, что пора за работу. Именно так и работают современные высокопроизводительные приложения.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Good practice по алгоритмизации в условиях асинхронно
Бороться со сложностью можно используя иерархические КА, в которых состояние само может быть КА.
Но "надрыв мозга" при составлении КА конечно же будет.
Кстати исходный "линейный" алгоритм (из того разряда, который я приводил в примере) отчасти так или иначе в явном виде содержит КА, поскольку состоит из:
1. Описаний последовательностей команд и проверяемых условий при приходе тех или иных событий
2. Описание своего рода "синхронизации" действий, т.е. что делать если в момент прихода события, на которое нужно реагировать, уже выполняется какое-то действие..
Честно говоря, по п.2 не вижу более естественного и популярного пути описания этой логики, чем КА.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, asimonenko, Вы писали:
A>>Все равно все сведется к автомату, ИМХО. Т.е. данные появляются асинхронно, и при определенных условиях (наборе данных) ты должен выполнить определенное действие.
A>>То же самое с сериализацией — при десериализации ты логично "двигаешь" автомат в нужную точку последовательностью входящих данных.
A>>Словом, КА — просто и надежно. Только его нужно сразу выявить, формализовать (куда-нибудь записать диаграммку) и реализовать на ранних стадиях, пока не наворочена неформализованная куча -)
G>Для автоматов нет способов борьбы со сложностью. Если состояний станет слишком много, то не не будет возможности как-то исправить.
Re[4]: Good practice по алгоритмизации в условиях асинхронно
Здравствуйте, sergunok, Вы писали:
S>Бороться со сложностью можно используя иерархические КА, в которых состояние само может быть КА.
S>Но "надрыв мозга" при составлении КА конечно же будет.
S>Кстати исходный "линейный" алгоритм (из того разряда, который я приводил в примере) отчасти так или иначе в явном виде содержит КА, поскольку состоит из: S>1. Описаний последовательностей команд и проверяемых условий при приходе тех или иных событий S>2. Описание своего рода "синхронизации" действий, т.е. что делать если в момент прихода события, на которое нужно реагировать, уже выполняется какое-то действие..
S>Честно говоря, по п.2 не вижу более естественного и популярного пути описания этой логики, чем КА.
Это теория, на практике автомат с нетривиильной логикой в котором более 10 состояний и от каждого более одного перехода — получается страшный макаронный код, который очень тяжело поддерживать. Все потому что нету у КА средств борьбы со сложностьюю
Re[3]: Good practice по алгоритмизации в условиях асинхронно
Здравствуйте, Aviator, Вы писали:
A>Здравствуйте, gandjustas, Вы писали:
G>>Смотри Rx A>Давно интересовался практическими применениями этой либы, может есть у кого случаи успешного применения в рабочих проектах?
Мне очень туго пришлось бы в последнем проекте без этой штуки. Особенно выручает в ситуациях, когда возникает необходимость отправить сервису команду А, асинхронно получить результат, потом на его сформировать команду Б ..., потом проделать тоже самое со следующим сервисом, и так далее, и так далее, а если в процессе произойдет ошибка, то послать первому сервису команду ...
Re[4]: Good practice по алгоритмизации в условиях асинхронно
Здравствуйте, Lazin, Вы писали:
L>Здравствуйте, Aviator, Вы писали:
A>>Здравствуйте, gandjustas, Вы писали:
G>>>Смотри Rx A>>Давно интересовался практическими применениями этой либы, может есть у кого случаи успешного применения в рабочих проектах?
L>Мне очень туго пришлось бы в последнем проекте без этой штуки. Особенно выручает в ситуациях, когда возникает необходимость отправить сервису команду А, асинхронно получить результат, потом на его сформировать команду Б ..., потом проделать тоже самое со следующим сервисом, и так далее, и так далее, а если в процессе произойдет ошибка, то послать первому сервису команду ...
Может быть приведешь примерчик кода того применения, которое порадоволо?
Re[5]: Good practice по алгоритмизации в условиях асинхронно
порадовало легкостью, с которой некая библиотека доступа к данным, не следующая общепринятым паттернам, может быть использована вместе с Rx. Здесь выполняется подписка на изменение данных, поступающих из некоего хранилища, query — запрос на подписку, OnCode — вызывается при возникновении разных ошибок, OnData — при появлении новых данных, Start — выполняет запрос, End — отменяет подписку. Все это безобразие приводится к интерфейсу IObservable с минимальными усилиями, без необходимости написания кучи boilerplate кода.
Но больше всего радует конечно же возможность комбинировать разные IObservable объекты.
Вот такой код, к примеру, у меня отвечает за отображение текущего состояния некоего объекта:
Если бы я не использовал Rx, то пришлось бы создавать объект — конечный автомат, который бы в ответ на события изменял свое состояние и сам был бы источником событий для пользовательского интерфейса. А здесь — все в одном месте, никакого явного состояния, хотя конечно, детали того как происходит подписка на те или иные события, спрятана в ф-ях SuiteXXX, но эти детали и не нужны коду, отвечающему за пользовательский интерфейс