Обновить

Комментарии 2

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

Хотелось бы увидеть конкретные цифры, какой-нибудь бенчмарк, чтобы понять, что именно и с чем мы сравниваем. Почему события захлёбываются, а IAsyncEnumerable - нет, если в конечном счёте и то и другое утыкается в UI, доступ к которому сериализован?

[...] появилась возможность использовать IAsyncEnumerable, позволяющие реализовать код профессионального уровня с линейной сигнатурой и преимуществами такими как:

  • Полное соответствие концепции чистой архитектуры

  • Масштабируемость

  • Полной контроль над потоками данных

  • Тестируемость

  • Отменяемость

  • Читаемость

  • Слабая связанность

Что такое "полное соответствие концепции чистой архитектуры"? Чем отличается от неполного?

Что такое "полный контроль над потоками данных"? Чем отличается от неполного? Почему у событий нет полного контроля? Почему нет остальных преимуществ?

Спасибо за вопросы — они по делу.

Начну с бенчмарков: их нет, и это честно. Чтобы сделать показательный тест, нужен целый проект, а на это уйдёт время. Если вам интересно — можете сами прогнать, я буду только рад увидеть цифры. Но суть не в скорости, а в управляемости: события толкают данные сами, а IAsyncEnumerable позволяет тебе решать, когда их брать. Это не «быстрее», это «удобнее» для сложных сценариев.

По поводу UI — вы правы, в конечном счёте всё упирается в UI. Но разница в том, кто задаёт темп: события могут захлебнуться, если данные летят быстрее, чем ты успеваешь их обрабатывать — и тогда приходится буферизировать вручную, что ведёт к росту памяти и нагрузке на GC. IAsyncEnumerable даёт контроль: хочешь — обрабатывай быстро, хочешь — поставь паузу.

«Полное соответствие чистой архитектуре» — громко сказано, согласен. В примере из статьи я использую прямое создание экземпляра FindDevicesService, чтобы не усложнять код и сфокусироваться на IAsyncEnumerable. В реальных проектах я использую DI и интерфейсы, но в статье это опущено, чтобы не отвлекать. Суть подхода — не в интерфейсах, а в управляемом потоке данных, отменяемости и линейном коде без Dispatcher.Invoke.

«Контроль над потоком» — это про возможность остановить, притормозить, отменить или перераспределить данные. События так не умеют: ты подписался — и данные летят сами, независимо от твоей готовности.

Статья не претендует на истину в последней инстанции. Это мой практический опыт, как уйти от Dispatcher.Invoke и событийного ада. Если есть конкретные сценарии, где этот подход не работает — буду рад обсудить. А с бенчмарками вы правы — было бы круто их добавить, но это уже за рамками формата.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации