Некоторое время назад авторы CAF-а (он же C++ Actor Framework) выкатили туториал warehouse-backend. Заглянул любопытства ради. Поделюсь некоторыми крайне субъективными наблюдениями.
Сперва небольшой дисклеймер. Поскольку я сам много лет делаю инструмент программирования на C++ в стиле асинхронного обмена сообщениями, то не могу быть объективным. Так что если ниже по тексту вам покажется, что меня заносит и я перебарщиваю с категоричностью, то значит вам не показалось, а меня занесло на самом деле 😉
Ну и да, чтобы было лучше понятно о чем написано ниже, было бы здорово сперва посмотреть туториал, хотя бы по диагонали. Если вы никогда в глаза не видели CAF или видели когда-то давно, то это может быть весьма любопытно.
Впечатление первое. Одно из главных
Глядя на код примеров ощущаю себя старым пердуном, застрявшим в начале 1990-х со своим ООП, и ничего не понимающим в красоте функционального кода.
Мне бы обычных классов с методами. А не лямбды внутри лямбды внутри лямбды, объединенные монадическими цепочками .filter().map().observe().transform().subscribe() (или это не монады вообще?)
В общем, с непривычки непросто. Какие-то сущности в виде отдельных типов оформляются, но только лишь для того, чтобы затем с потрохами этих типов работать напрямую внутри лямбда функций.
Впечатление второе. Нехороший привкус vendor lock-in
Очень смущает обилие того, что берется из пространства имен caf. Тут тебе и caf::net, и caf::cow_string, и caf::json_object, и caf::logger, и пятое, и десятое.
Такое ощущение, что авторы CAF-а создали вокруг своего инструмента целую замкнутую и самодостаточную экосистему.
Наверное, непритязательным пользователям удобно: берешь один CAF, а вместе с ним получаешь и сеть (включая TLS и HTTP-сервер), и JSON, и конфиги, и еще кучу всего полезного. И, полагаю, это хорошо для подсаживания пользователей на иглу конкретного продукта. Кто сказал vendor lock-in? 😉
Мы когда-то давно вокруг SObjectizer-а тоже пытались что-то подобное построить -- у нас и so_log был, и so_sysconf, и еще что-то. Это было хорошо двадцать лет назад, когда мы были в замкнутом мире внутренних продуктов компании Интервэйл, в которой SObjectizer когда-то появился.
Но сейчас, когда в мире C++ столько всего разного и конкурирующего друг с другом, мне показалось более разумным сконцентрироваться только на ядре SObjectizer-а. А уже пользователь может выбрать для себя Asio или libuv, spdlog или Boost.Log, RESTinio или Beast, nlohmann::json или simdjson, и т.д., и т.п.
Так что я лично придерживаюсь мнения, что инструмент должен делать лишь одну вещь, а остальные потребности, будь то парсинг JSON или прием/отсылка UDP-датаграмм, закрывается внешними инструментами.
Впечатление третье. Незначительное
Есть в туториале пример с typed_actor. На первый взгляд, штука прикольная, когда мы на уровне типа описываем то, на что актор реагирует.
Признаться, сам несколько раз задумывался о том, а можно ли сделать это в SObjectizer. Каждый раз это упиралось в растущий как снежный ком клубок вопросов, что в итоге складывалось впечатление, что овчинка не стоит выделки.
На практике у меня нередко возникают ситуации, когда есть агент со своим набором обрабатываемых сообщений. И на время отладки нужно добавить агенту обработчик еще одно сообщения, а затем убрать из финальной версии. Если агент не типизирован, то делается это легко и непринужденно. Тогда как в случае типизированного агента придется временно менять его описание (т.е. его тип), потом возвращать обратно. Это какие-то слишком уж глобальные изменения.
Плюс к тому, перечень разрешенных входящих сообщений -- это неплохо, но если у агента есть состояния, то очень желательно было бы задекларировать в каких состояниях что обрабатывается. А для этого простого перечня входящих сообщений недостаточно.
Так что типизированные акторы, имхо, фича прикольная, но на практике не так уж и полезная.
Вместо заключения
Признаюсь честно, лет 7-8 назад у меня еще были и время, и силы, и желание брать и смотреть на чужие похожие разработки (будь то CAF, Akka или Orleans). Теперь уже нет ни того, ни другого, ни третьего.
Все эти реализации модели акторов получаются настолько разными, что смысл подобного сравнения от меня ускользает. Ну вот есть в CAF фича X, а в Akka фича Y. Ну есть и что?
Совсем другое дело, когда ко мне приходят с конкретным вопросом. Типа вот у меня есть такая проблема, как я могу ее решить с помощью SObjectizer-а? И могу ли вообще?
Ну или что-то вроде: вот я в CAF/Akka/Orleans делаю вот это вот так-то, а как это будет в SObjectizer?
Вот это для меня предметный разговор, из этого наверняка можно что-то полезное извлечь. На это я готов тратить свое время.
Но вот на то, чтобы посмотреть что где-то там новенькое появилось... Увы, не хочется.
И, возможно, это и есть для меня самое главное впечатление 🙂
Разработчики же CAF, как я понял, сейчас пытаются монетизировать известность своего продукта. От всей души желаю им успеха на этом непростом пути.
Признаюсь, я уже давно не рассматриваю CAF или Akka в качестве конкурентов SObjectizer-у. Это все настолько разные продукты, что общего в них мне видится очень и очень мало. По сути, это как сравнивать обычный слесарный молоток, кувалду и отбойный молоток. Вроде как все это разновидности молотков, но не так уж и много случаев, когда они могут быть взаимозаменяемы.