суббота, 28 марта 2020 г.

[prog.actors] Почему я не считаю упомянутых в статье на Хабре акторов настоящими акторами

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

К сожалению, получилось как в анекдоте: "Вот нутром чую, что 0.5 плюс 0.5 будет литр, а математически выразить не могу". Т.е. ощущение "должно было быть попроще" присутствует, но вот чтобы выяснить, что именно и как можно (и нужно бы) упростить... На это не хватает времени и терпения.

Это вообще достаточно сложная проблема, с которой я регулярно сталкивался будучи тимлидом. Делаешь code review подчиненного и явно ощущаешь, что реализация переусложнена, что можно проще. Говоришь "здесь что-то слишком сложно, должно быть проще", а на встречный вопрос "А как проще?" сходу ответ дать не можешь. Потому что для того, чтобы дать такой ответ, нужно самому сесть и плотно поработать над этой задачей. А это значит, что ты мало того, что будешь вынужден переделать работу, которую должен сделать твой подчиненный, но еще и не успеешь сделать что-то другое, что ты никому не можешь делегировать.

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

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

Дело в том, что в статье автор повсюду упоминает акторов и, как мне показалось, пребывает в уверенности, что использует "акторный подход". Хотя я (пока еще) убежден, что это не так. И в данном посте попробую объяснить, почему мне кажется, что использованные в статье "акторы" на самом деле "акторами" не являются.

среда, 18 марта 2020 г.

[prog.flame] Ай да молодцы в Dropbox! Взяли и переписали свой sync engine на Rust. Ну молодцы же, да?

Речь про вот этот пост: Rewriting the heart of our sync engine. Dropbox переписал часть своей системы, отвечающей за синхронизацию, с Python-а на Rust и выкатил на публику победную реляцию об этом достижении.

Вот казалось бы, имей голову на плечах и напиши все сразу на C++... И работало бы это все годами.

Не нравится C++, а Rust-а еще нет не свете? Но ведь есть Ada, есть Eiffel...

Но нет. Сперва нужно написать на Python.

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

А потом выбросить результаты всех трудов на помоечку (с) и с криками восторга и другими проявлениями щенячей радости переписать все на Rust.

Ну и для тех, кто типа умеет читать между строк: это пост не про то, что C++ хорош, а Rust плох. Rust хорош. И для подобных задач его выбор ничуть не хуже, а может и лучше, чем выбор C++. Он про то, что выбор по принципу "пользуем то, на что надрачиваем, а ничего другого просто не знаем", в конце-концов приводит к потере времени и денег.

Да и еще не могу удержаться и не пройтись по любимой теме:

Almost all of our code runs on a single thread (the “Control thread”) and uses Rust’s futures library for scheduling many concurrent actions on this single thread. We offload work to other threads only as needed: network IO to an event loop, computationally expensive work like hashing to a thread pool, and filesystem IO to a dedicated thread. This drastically reduces the scope and complexity developers must consider when adding new features.

Это как раз то, что SObjectizer умеет делать с самого начала: распределять работу между сущностями, каждая из которых работает на нужной ей контексте. Хоть на общей рабочей нити, хоть на пуле потоков, хоть на выделенной отдельной рабочей нити. Собственно, для этого SObjectizer и создавался много лет назад.

четверг, 12 марта 2020 г.

[prog.c++.tiredness] Написал мета-функцию transform и чё-та приуныл...

Сегодня с утра потребовалось реализовать мета-функцию transform для списка типов в C++. Т.е. в transform передается мета-функция трансформатор и список типов, а на выходе получается преобразованный список типов. Типа такого:

using T = transform_t<std::decay, type_list<int, int&, const string&>>;
// T == type_list<int, int, std::string>

Задался целью сделать этот transform самостоятельно, опираясь только на детали реализации других мета-функций, которые написал где-то в начали осени 2019-го по следам прочитанных в Интернете материалов.

Убил часа полтора. Тупил невероятно. Но сделал. Не заглядывая в Интернет.

Никакого удовольствия от решения этой частной задачки не получил. Зато возникло ощущение, что чего-то для меня уже слишком много. Либо конкретно C++. Либо программирования вообще...

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

Либо специализацию, поскольку C++ реально подза*бывает, чем дальше, тем больше. И сам язык, в котором невероятная мощь сочетается с невероятной кривизной и, имхо, слишком уж высоким темпом развития в последние годы. И фрагментированное коммьюнити с чрезвычайно сильно развитым NIH-синдромом.

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

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

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

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

вторник, 10 марта 2020 г.

[prog.c++.bicycle] I'm working on the first draft of experimental type-safe router for RESTinio

The express-like router is available in RESTinio for several years. I think it is a very easy to use tool, that is familiar to many developers. But it has some congenital defects I wanted to repair for a long time.

The congenital defects of express-like router

The propensity to errors

The first defect is that express-like router is error-prone and isn't friendly for repeated cases. Let's look at one of the examples from RESTinio, express_router:

пятница, 6 марта 2020 г.

[prog.c++] Реинкарнация procxx под именем procyy

К сожалению, библиотека procxx выглядит окончательно заброшенной своим автором. Поэтому я решил не отсылать PR в procxx, т.к. его вряд ли приняли бы, а сделал форк под другим именем:

https://github.com/eao197/procyy

Этот форк лежит, в общем-то в том же виде, в котором и procxx. Никаких тестов, продвинутых примеров, проектных файлов для CMake или чего-нибудь еще. Как взял, так и оставил :)

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

Нет и планов добавить procyy в conan, vcpkg, hunter или какой-нибудь другой менеджер зависимостей. Лично мне это не нужно, а если кому-то нужно, тот пусть и берет на себя все эти заботы. Простите.

PS. Кидаться в меня помидорами по поводу качества кода нет смысла, программист из меня так себе. Получилось как получилось. Конструктивные соображения по поводу улучшения кода продуктивнее оформлять в виде issues.

среда, 4 марта 2020 г.

[prog.c++.actors] Обновленная версия презентации "Actor Model and C++: what, why and how?"

Обновил свою презентацию более чем трехлетней давности. Поскольку что-то в ней уже устарело за это время. А что-то все еще актуально. Так же добавил в презентацию ссылки на малоизвестные широкой публике разработки actor-zeta и rotor. Ну не CAF-ом же единым, в конце-концов...

Так же эта презентация доступна на SlideShare, а PDF-ку отдельно можно скачать с SourceForge.

Я сделал пост на Reddit-е и у себя в LinkedIn. Если кто-то сочтет возможным опубликовать ссылку на SlideShare еще на каких-то ресурсах, то это будет здорово.

[prog.c++.actors] Довелось еще раз посмотреть в сторону CAF

Решился намедни обновить свою старую уже презентацию Actor Model and C++: what, why and how?, поскольку за прошедшее время многое уже изменилось. И, наверное, впервые с 2016-го года еще раз посмотрел в сторону главной на данный момент реализации модели акторов для C++, библиотеке CAF (она же C++ Actor Framework).

Несколько прифигел.

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

Во-вторых, похоже, уже нет шансов хоть как-то побороться с CAF-ом за популярность в C++ мире. Больше двух тысяч звезд на github-е против шести десяков (именно десятков) у SObjectizer-а. На HackerNews посты про CAF собирают под сотню поинтов, тогда как аналогичные для SObjectizer-а -- в лучшем случае 2-3 поинта.

Что называется, почувствуйте разницу.

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

Собственно, вывод из этого простой: никогда SObjectizer не станет популярным и широко востребованным инструментом среди C++ников.

Следовательно, нет смысла пытаться двигаться в этом направлении. Значит SObjectizer будет развиваться дальше без оглядки на то, чтобы кому-то понравится. Или чтобы добавить в SObjectizer что-то, что позволит ему "конкурировать" с чем-то еще.

Это означает, что в последующие версии SObjectizer-а будет добавляться только та функциональность, которая потребуется нам самим. А так же те фичи, которые у нас попросят. Не более того. Нам SObjectizer нужен как относительно небольшой (а по сравнению с нынешним CAF-ом он реально небольшой), практичный и мощный инструмент.

Ну, например, мы используем SObjectizer в тестах RESTinio для проверки поведения RESTinio в условиях многопоточности. И этот сценарий использования SObjectizer-а выглядит вполне себе естественным. Поскольку SObjectizer относительно небольшой. Тогда как применение для этих целей CAF-а мне сложно представить... Наверное, можно. Но, блин, как из пушки по воробьям.

Так что постараемся сохранить небольшой размер и сложность SObjectizer-а. А создание комбайна на все случаи жизни оставим разработчикам CAF-а.

В-третьих, в очередной раз пришел в выводу, что у меня лично, видимо, совсем другие представления о разработке софта, нежели у авторов CAF-а. Поэтому SObjectizer получается именно таким, какой он есть: многословный и несколько старомодный, базирующийся на ООП из конца 1980-х и 1990-х. Ибо я на собственном опыте неоднократно убеждался, что в таком стиле можно писать софт, который развивается в течении многих лет, который вбирает в себя все больше и больше функциональности, разрастаясь в объеме в разы, если не на порядок. И который, при этом, все еще остается обозримым и поддающимся сопровождению.

Но вот как на том же CAF-е делать большие, сложные и эволюционирующие программые системы, когда там лямбда на лямбде и лямбдой погоняет... Вот честно, не представляю.

При этом я ни в коем случае не говорю о том, что подход разработчиков CAF-а плох. Возможно, он намного лучше моего. И у множества людей, выбравших CAF, нет никаких проблем. Может это как раз передовой подход, который либо уже стал мейнстримом в C++, либо станет в ближайшее время. А я этого не понимаю в силу своей замшелости и зашоренности.

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

Ну и, если вспомнить "во-вторых", остается надеятся, что SObjectizer станет выбором для тех немногих, кто, как и я, не очень хочет писать сложный прикладной код в стиле CAF-а.

Кстати говоря, а что читатели блога думают о CAF-е и о том, как выглядит разработка на акторах с использованием CAF-а?

Заодно, если кому-то чего-то не хватает в SObjectizer-е, или же что-то мешает в SObjectizer-е, то об этом можно сказать прямо сейчас. Например, кому-то мешало использование RTTI в SObjectizer-е. Эта проблема все еще актуальна для кого-нибудь? Имеет ли смысл думать над SObjectizer-ом, который бы не был завязан на RTTI?


Надеюсь, что обновленную версию "Actor Model and C++: what, why and how?" получится опубликовать сегодня во второй половине дня.