среда, 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?" получится опубликовать сегодня во второй половине дня.

понедельник, 2 марта 2020 г.

[prog.c++] Есть желание реинкарнировать библиотеку procxx

Тут такое дело... Жила-была себе небольшая, простая в реализации и симпатичная C++11 библиотека procxx для запуска дочерних процессов в Unix-ах. Мы нашли её года четыре назад и несколько раз за это время использовали то тут, то там. И даже отослали автору какие-то PR.

Давеча потребовалось использовать procxx еще раз и в ее реализации обнаружились некоторые фатальные недостатки. Для устранения которых потребовалось существенно ператрахнуть (с) потроха procxx. И вот теперь, когда новая реализация procxx задышала, возник вопрос: а что с этим делать дальше?

Проект procxx выглядит заброшеным. В репозиторий несколько лет ничего не коммитили, на issue нет реакции. Сам автор, судя по его мизерной активности на github-е, переключился на Rust. Так что, в принципе, можно было бы сделать pull-request для procxx, но смысла в этом я лично не вижу. Тем более, что подобный вопрос я открыл в качестве issue, но никакой реакции пока не последовало (вполне ожидаемо).

Тем не менее, выбрасывать procxx "на помоечку" (с) не хочется. Ну реально простая и удобная библиотека без каких-либо серьезных наворотов в реализации (по крайней мере до того, пока я не запустил туда свои шаловливые ручонки). Осваивается влет, буквально берешь и пользуешься.

Поэтому есть желание реинкарнировать procxx.

Но т.к. автор ничего на эту тему не сказал, то мне стремно использовать procxx в названии моего форка. Было желание назвать обновленную версию procxxrv (от procxx-revisited) или procxx-ng (от procxx-new-generation). Но с такими названиями получается, что я как бы пытаюсь заработать очки на популярности старой procxx. Что не есть хорошо.

Соответственно, если кто-нибудь поделится в комментариях хорошим названием для подобной библиотеки (т.е. библиотеки для простого запуска дочерних процессов в Unix-ах), то вы очень мне поможете.

Посмотреть на то, что есть в procxx-revisited на данный момент можно здесь (ветка revisited). Любые конструктивные замечания/предложения, естественно, приветствуются.

суббота, 29 февраля 2020 г.

[prog.flame] Наглядное подтверждение изречения про два типа языков программирования...

...которое, если я не ошибаюсь, звучит как-то так: "Есть всего два типа языков программирования: те, которые все ругают, и те, которыми никто не пользуется". И вот статья про язык Gо под названием "I want off Mr. Golang's Wild Ride" наглядно показывает, что Go принадлежит к языкам первого типа.

Вообще, как мне думается, данная статья является еще одним проявлением давнего вселенского плача под названием "worse is better". Может из молодежи кто-то не в курсе, но лет 15 назад вокруг этого самого "worse is better" в этих наших интернетиках были большие срачи. Хотя те, 15-летней давности срачи были всего лишь очередной волной подобных срачей после самой формулировки этого принципа в начале 1990-х.

Т.е. суть в том, что в реальной жизни "побеждает" не то, что "лучше" по какому-то абстрактному набору "хороших" критериев. А то, что позволяет "легко", "просто" и "дешево" решать насущные проблемы здесь и сейчас. При этом работающее решение может быть не самым красивым, эффективным и надежным. Но оно, определенно, является good enough.

Собственно, упомянутая статья наглядно это демонстрирует на примере косяков языка Go и его стандартной библиотеки. Да, косяки есть. Да и вообще сам по себе Go не столько прост или, правильнее сказать, примитивен. Это откровенно "тупорылый" язык.

Только вот те, кто гнобят Go и противопоставляют Go другим, гораздо более сложным в освоении языкам, не понимают простой вещи: именно эта "тупорылость" и делает Go мегаценным для определенной части рынка разработки ПО.

Потому что в этой части рынка ничего сложнее нынешнего Go и первых версий Java/C#, в которых еще и генериков не было, просто не приживается.

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

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

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

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

При этом первый тип программистов не нужно путать с другим типом, "пуристами-идеалистами", который так же нередко встречается: разработчики, для которых качество кода отвязано от работоспособности кода. Т.е. если "пуристы-прагматики" стараются писать работающий код в идиоматичном стиле, заботясь о его лаконичности, понятности, расширяемости и поддерживаемости, то "пуристы-идеалисты" просто пишут код в идиоматичном стиле (и далее по тексту), но вот цель написать именно работающий код теряется где-то по дороге.

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

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

Так вот, по моему мнению, "реалистов" гораздо больше, чем "пуристов-прагматиков". Можно долго и много рассуждать, почему это так. Но тем не менее, мне думается, что "реалистов" больше. Се ля ви, ёптыть.

Ну и следствием из этого является то, что языки вроде Go, Java или даже чистого Си, находят гораздо более широкое применение, нежели что-то вроде Modula-2, Eiffel, Ada или Rust. Просто Go и Java гораздо ближе к народу, под которым прежде всего понимается множество "реалистов".

Отсюда и плач на тему "worse is better": если ты "пурист-прагматик" (не говоря уже про случай "пуриста-идеалиста"), то то, что для тебя "worse", для "реалиста" как раз таки "better". И наоборот. В общем, извечный спор "тупоконечников" и "остроконечников". Ну а упомянутая вначале статья, похоже, была написана "пуристом-прагматиком". Отсюда и ее содержание.


PS. В качестве дисклаймера. Я не пытался сказать, что есть только три типа разработчиков. Я упомянул лишь три ярких типа. Есть, как минимум, еще один яркий тип -- "рукожопы". А так же большое количество менее ярких. А так же типы, с которыми я либо еще не сталкивался, либо про которые не вспомнил по ходу написания этой заметки.

среда, 19 февраля 2020 г.

[prog.sadness] Чем больше шуму вокруг C++20 тем больше хочется уйти с C++ вообще

Да уж... Давно я не испытывал такого сильного желания свалить с C++ на какой-нибудь другой язык программирования, как после новостей о завершении работ над C++20 😒 😒 😒

Я даже не могу понять, что тому виной. Может быть то, что хочется держаться подальше от языка, в котором, в принципе такая хитровывернутая система модулей, что сходу в нее и не въедешь. Тем более после 35 лет вполне себе успешного существования без этих самых модулей... Как по мне, так C++ нужно было оставлять без модулей и дальше, а проблему долгой компиляции решать каким-то другим способом.

Может быть потому, что не хочется в очередной раз проходить путь адаптации кардинальных изменений в новом стандарте. Я уже через это прошел когда появился C++98, а потом и C++11. Оба раза это занимало годы и годы оглядываний на старые компиляторы, в которых стандартом либо еще не пахнет, либо же он реализован частично. Даже сейчас еще бывают случаи, когда приходится пользоваться компилятором с неполной поддержкой C++11... Так что впереди еще лет десять привыкания к C++20.

Может быть потому, что стандарты каждые три года -- это слишком часто, как мне кажется. Не смотря на то, что в информационных технологиях все развивается быстро, но индустрия-то оказывается не готова к массовому переходу на новый стандарт за то время, пока готовится следующий. Тому же C++17 уже три года, а ведь он есть и доступен далеко не везде.

Может быть потому, что языку 35 лет, новые стандарты начали штамповать каждые три года, а важные принципиальные разногласия в C++ сообществе так и не устранены. Например, исключения и RTTI часто оказываются под запретом, а сама стандартная библиотека языка вряд ли сможет работать с полностью отключенными исключениями. Или без возможности использовать динамическую память.

Может быть потому, что C++ реально начинает прогибаться до земли под собственной тяжестью, поскольку когда пишешь вот в таком вот стиле, то начинает казаться, что слишком уж много приходится указывать вручную:

class Demo {
  [[nodiscard]] bool empty() const noexcept;
  ...
};

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

Может быть это старческая боязнь перемен...

А скорее всего все это в совокупности.

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

Но все равно есть какое-то подсознательно-неосознанное ощущение "а не пора ли свалить с этого перегруженного корабля, у которого на мостике творится одно, в машинном отделение -- другое, а в трюме все вообще по-другому?"

воскресенье, 16 февраля 2020 г.

[life.cinema] Как бы я попробовал бы сделать продолжение Терминатор-2

При написании последнего кинообзора не хватило времени и желания развить мысль по поводу безнадежно угробленной франшизы "Терминатора". А хотелось бы высказать и свою идею о том, как можно было бы попробовать сделать прямое продолжение "Терминатор-2", отбросив снятые ранее третью, четвертую и пятые части. Попробую сделать это сегодня. При этом хочу предупредить, что описанная ниже идея посетила меня еще до того, как мне стали известны общие детали сюжета "Терминатор: Темные судьбы".

Итак, идея в том, что в рамках рассказанной в первых двух фильмах истории Skynet отправил в прошлое не двух T-800, а трех. Второго из них уничтожили в первом "Терминаторе", третий стал главным героем "Терминатор-2". А вот первый был отправлен Skynet-ом в прошлое еще раньше, еще до действий первого фильма. Его задачей было отследить происхождение Джона Коннора.

Нас же не удивляет, что в первом фильме терминатор из будущего прибыл именно в Лос-Анджелес и не удивляет, что он начал разыскивать Сару Коннор, хотя точно не знал какую именно. Но откуда у Skynet-а появилась информация о Саре Коннор из Лос-Анджелеса?

[prog.c++] Пришли вести об окончании формирования C++20, только вот...

...почему-то вспоминается старое проклятие: "Да шоб ты жил в эпоху перемен!"

Возможно, на мне сейчас сказывается усталость после нескольких непростых рабочих недель, но грядущее пришествие C++20 я воспринимаю как непростую историю с Python2 и Python3. В этом посте постараюсь объяснить почему у меня такое ощущение.

Мне думается, что только вот сейчас, к 2020-ому году в большинстве своем состоялся уход от C++98/03 к C++11/14/17. Т.е., несмотря на то, что где-то еще живут большие кодовые базы на C++98, все-таки нормой становится современный C++. И это хорошо.

Хотя еще много мест, где современный C++ -- это в лучшем случае C++11 на уровне gcc-4.8.

И поэтому даже сегодня, в 2020-ом году, при разработке C++кода, которому грозит либо применение на широком спектре компиляторов, либо же который разрабатывается под специфические нужды конкретного заказчика, то и дело приходится ограничиваться C++11... Если честно, я на этом фоне даже думаю, что в прошлом году сильно ошибся, переписав SObjectizer-5.6 сразу на C++17, а не на C++11 (ну или хотя бы на C++14).

И вот что тут важно: в принципе, даже проект, который был написан на C++17, при необходимости можно переделать под C++14 или С++11. Понятно, что делать это неприятно, но если за это платят, то почему бы и нет.

Механика такого даунгрейда так же понятна и уже неоднократно проходилась. Вещи типа [[nodiscard]] или [[fallthrough]] помещаются под макросы, фишки типа constexpr if или structured binding не используются, fold expression разворачиваются вручную... Да, объем работы увеличивается. Но все-таки он не превышает некоторого психологически-приемлемого уровня.

Но C++20 вносит в язык несколько принципиально новых возможностей. Навскидку: модули, концепты, короутины и гораздо более продвинутый constexpr. Как отказаться от их использования так, чтобы разработанный код можно было использовать и в C++11, и в C++20, я не представляю.

А это означает, что C++20 вводит еще более строгий и жесткий "водораздел" между старым и новым кодом, чем это было даже после появления C++11. Т.е., если код начал писаться под C++20, то только под C++20 его и можно будет использовать. И простого даунгрейда написанного под C++20 кода под старые C++ стандарты (пусть даже старым будет C++17) уже не будет.

Для разработчиков прикладного кода на C++ это вряд ли будет представлять проблему. А вот для разработчиков библиотек, вроде нас, это будет проблема. Ведь если портировать библиотеку под C++20, то ее не смогут использовать те, кто вынужден оставаться на C++11/14/17. А таких в ближайшие 4-5 лет, а то и больше, будет большинство.

Что, как мне кажется, для библиотеко-писателей означает одно: если хочешь, чтобы твоя библиотека использовалась широко, то сиди на C++11 и не рыпайся. До C++32. Потом можно будет на C++20 перебраться.

PS. Сам в последнее время для одного из клиентов вынужден оставаться в рамках C++11. И не смотря на то, что между C++14 и C++11 изменений не так уж и много, мне кажется, что даже по сравнению с C++14 одиннадцатые плюсы уже неюзабельны :(