Здравствуйте, gyraboo, Вы писали:
G>Здравствуйте, dsorokin, Вы писали:
D>>... И там тоже есть место всем этим транзакциям, исключениям, потокам исполнения и тому подобному.
G>Есть-то есть, но через одно место. Например, в реактивном стэке Spring Reactor/Webflux стримы выполняются на небольшом кол-ве системных тредов, т.е. сами реактивные стримы не многопоточны, поэтому если разработчик выполняет любую блокирующую операцию на стриме неправильно ("неправильно" — это обычным вызовом блокируюшей операции), то он блочит весь стрим, т.е. блочит все сотни других и превращает высоконагруженный скоростной стрим в узкое место. G>А блокирующие операции — это чуть ли не 90% всех БД и интеграционных операций — вызовы REST API, вызовы к файловой системе, работа с БД, даже просто поставить паузу через Thread.sleep. И поэтому реактивщина тянет за собой целый ворох специфики — чтобы работать с БД в неблокирующем стиле, нужен реактивный jdbc-драйвер, чтобы работать в неблокирующем стиле с REST API, нужен особый неблокирующий REST API-клиент, чтобы работать в неблокирующем стиле с входящими веб-запросами, нужен особый неблокирующей веб-сервер. В общем, это полностью новый мир со своими правилами, и многие из этих библиотек ещё сырые (например, в реактивном JPA, насколько знаю, до сих пор не реализованы OneToMany/ManyToMany), реактивный сервер netty имеет баги и утечки (сам лично находил), т.е. я бы сказал, что для корпоративной разработки функциональщина и реактивщина ещё не "дозрели" и остаются либо вотчиной "академиков", либо хайлоада, где имеет смысл жертвовать в угоду хайлоаду (типа простейших микросервисов гейтвеев), но желательно, чтобы бизнес-логики на функциональщине было написано минимум, потому что попытка писать на ней сложную бизнес логику приводит к миллиону не-императивных функциональных конструкций, в которых потом никто, даже сам автор, разобраться не в силах, и случайно посадить в этом нагромождении баг проще простого, например вставив куда-нибудь блокирующую операцию, что превращает всё это великолепное нагромождение функциональных операторов в тыкву.
Если ты про async-await, то в языках типа C# и F# весь IO должен быть явно определен в терминах асинхронных вычислений. Это ограничение метода реализации.
С другой стороны, в том же Haskell все стандартные операции IO внутри рантайма являются неблокирующими (асинхронными) через select/poll/epoll. И это делается прозрачно для пользователя за счет зеленых потоков. Код пишется как обычно, то есть, якобы как синхронный, но на деле он — асинхронный. Я так понимаю, что в тех же Go и Erlang ситуация похожая (вот, не смог себя заставить до конца прочитать учебник по Go этим летом)