четверг, 7 сентября 2017 г.

[prog.actors] Хотите решить задачу с помощью акторов? Спросите меня как! :)

После того, как мне довелось разным людям в разных местах рассказывать про Модель Акторов вообще и про SObjectizer в частности, сложилось впечатление, что продвижению Модели Акторов в массы препятствует две вещи:

  1. Отсутствие понимания того, что такое Модель Акторов вообще. Это, на самом-то деле, совсем не проблема. Очевидно, что всего на свете знать нельзя, а объяснить основные принципы работы Модели Акторов можно буквально на пальцах (что, кстати говоря, подтверждается практикой).
  2. Отсутствие понимания того, как эту самую Модель Акторов, принципы которой можно объяснить на пальцах, применить для решения практических задач.

Тут можно провести аналогию с молотком: понять как действовать молотком не сложно, не сложно и научить им бить. Гораздо сложнее разобраться куда же именно и с какой силой стукнуть молотком дабы получить нужный результат. Вот с Моделью Акторов, имхо, происходит тоже самое. Когда у человека есть конкретная задача, то не факт, что он может представить себе, как же ее решение будет выглядеть на акторах. Ибо понимать принцип -- это одно, а сделать декомпозицию конкретной задачи -- это другое.

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

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

Зачем это нужно мне? Очевидно, что мои цели исключительно корыстные ;) Прежде всего мне нужен материал, на основе которого можно было бы убедительно рассказывать людям о том, где применение Модели Акторов уместно, а где нет. Кстати говоря, неуместность применения Модели Акторов -- это актуальный вопрос. Бывает, что люди слушая про Модель Акторов теряют представление о том, что данная модель применима далеко не всегда. И хорошо бы уметь вовремя различать, где имеет смысл брать акторов, а где этого делать не нужно. Так же мне полезно прикидывать, насколько наш SObjectizer пригоден для решения тех или иных задач. Опыт показывает, что это сильно идет на пользу SObjectizer-у. А т.к. сам SObjectizer распространяется под BSD-лицензией (бездвоздме т.е. даром), то это пойдет на пользу и всем, кто воспользуется SObjectizer-ом.

Зачем это нужно вам? Ну мало ли :) Может вы хотите убедиться, какая все-таки гадость, эта ваша Модель Акторов, а вот вы молодец, когда придумали свое решение без использования акторов ;) Или может вы правда ломаете голову над чем-то и не прочь бы посоветоваться с умным человеком простофилей, который готов тратить свое время бесплатно. Ну или вам просто захотелось пообщаться ;)

В общем, если есть задачка и желание ее обсудить, то милости прошу. Описывайте свои задачки в комментариях к этой заметке (можно в G+), либо по почте eao197 на gmail тчк com, либо со мной можно связаться через FB, LinkedIn или Habrhabr.

PS. Запись специально повисит вверху до сентября. Но, если дело пойдет, можно будет заказать продление ;)

пятница, 14 июля 2017 г.

[prog.c++14] so_5_extra-1.0.1 и so-5.5.19.3

Сегодня мы выкатили очередную версию so_5_extra -- 1.0.1, а накануне обновили SObjectizer до версии 5.5.19.3. Доступно все, как обычно, на SourceForge: здесь so_5_extra, здесь SObjectizer.

В so_5_extra-1.0.1 добавлена всего одна фича: это collecting_mbox.

Смысл collecting_mbox в том, что иногда агенту X нужно получить строго N сообщений типа M от других агентов. Ну вот, например, стартует родительский агент-менеджер и создает пять нужных ему дочерних коопераций. Каждая дочерняя кооперация тратит какое-то время на свои начальные действия (например, загружается конфигурация, устанавливается подключение к БД, инициализируется внешнее устройство и т.д.), после чего отсылает родителю сигнал о том, что дочерняя кооперация готова. Соответственно, родительскому агенту нужно получить все пять сигналов о готовности дочерних коопераций, лишь после этого родительский агент сможет продолжать работать.

понедельник, 10 июля 2017 г.

[prog.c++14] Развернуть std::tuple в вызов конструктора базового класса

Давеча упоролся шаблонами настолько, что потребовалось сделать на C++ что-то вот такое (проще сперва показать на примере, а уже потом рассказывать словами):

templatetypename First_base, typename Second_base >
class Some_complex_template
   : public First_base // Boom #1
   , public Second_base // Boom #2
{
public :
   // Constructor.
   templatetypename... First_base_args, typename... Second_base_args >
   Some_complex_template(
      First_base_args &&...first_args, // Args for the first base class.
      Second_base_args &&...second_args ) // Args for the second base class.
      : First_base{ std::forward<First_base_args>(first_args)... }
      , Second_base{ std::forward<Second_base_args>(second_args)... }
      {}
   ...
};

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

Насколько я понимаю, C++ не позволяет написать фукнцию/метод с переменным количеством параметров вот так: f(First &&...first, Second &&...second), что логично, т.к. при вызове f(a1, a2, a3, a4, a5) невозможно понять, что из a(i) относится к first, а что к second.

Поэтому выход из ситуации сейчас ищется в использовании std::tuple вот в таком сценарии:

templatetypename First_base, typename Second_base >
class Some_complex_template
   : public First_base
   , public Second_base
{
public :
   // Constructor.
   templatetypename... First_base_args, typename... Second_base_args >
   Some_complex_template(
      std::tuple<First_base_args...> && first_args, // Args for the first base class.
      std::tuple<Second_base_args...> && second_args ) // Args for the second base class.
      : First_base{ /*some magic is required here!*/(first_args)... }
      , Second_base{ /*some magic is required here!*/(second_args)... }
      {}
   ...
};

Но вот тут возникает вопрос, как же распаковать содержимое std::tuple в вызов конструктора базового типа?

В принципе, вся эта магия с распаковкой std::tuple в вызов некоторой функции f хорошо проиллюстрирована на том же cppreferece.com в описании возможной реализации функции std::apply. Но есть нюанс: нам нужно сделать вызов конструктора базового типа, поэтому у нас нет возможности заводить вспомогательные функции, вроде apply_impl, в которые передается дополнительный аргумент std::index_sequence...

Или все-таки есть?

пятница, 7 июля 2017 г.

[prog.c++] Программирование на шаблонах плохо дружит с программированием на бумаге

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

Однако, если серьезно упороться C++ными шаблонами, то пользы от предварительного программирования на бумаге оказывается заметно меньше. Думаю, это потому, что C++ я знаю не очень хорошо, поэтому не могу на бумаге написать сложный код с шаблонами так, чтобы затем не пришлось его сильно переделывать из-за того, что компилятор на тему использования шаблонов думает совсем по-другому :( Из-за этого намного проще писать код прямо в Vim-е, пытаться его компилировать, сразу же исправлять те места, по которым у меня с компилятором (и со стандартном) обнаруживаются принципиальные расхождения. Затем все повторяется снова и снова, пока я не получаю то, что мне нужно, причем так, чтобы это компилировалось и VC++, и Gcc, и clang.

Однако, от того, что код начинает появляться прямо сидя за компьютером, зачастую я не знаю, как именно будет использовать какая-то новая сущность. Поэтому на начальном этапе настоящая беда и комментариями, и с самими наименованиями в программе. А для того, чтобы все это можно было со временем доработать напильником и довести до приличного состояния, код щедро размечается тегами FIXME. И выглядит это приблизительно вот так:

template<
   typename COLLECTING_MSG,
   typename TRAITS = runtime_size_traits_t,
   typename LOCK_TYPE = std::mutex >
//FIXME: should it be final or not?
class mbox_template_t final
   : public ::so_5::abstract_message_box_t
   , protected TRAITS::size_specific_base_type
   , protected ::so_5::details::lock_holder_detector< LOCK_TYPE >::type
   {
      using specific_base_type = typename TRAITS::size_specific_base_type;

      //FIXME: document this!
      using config_type = details::config_type< COLLECTING_MSG, TRAITS, LOCK_TYPE >;

      //FIXME: document this!
      using messages_collected_builder_t = typename
            details::collected_bunch_type_selector< config_type >::builder_type;
   public :
      //FIXME: document this!
      using messages_collected_t = typename 
            details::collected_bunch_type_selector< config_type >::message_type;

   private :
      //FIXME: document this!
      using messages_collected_subscription_type = typename
         std::conditional<
               is_mutable_message< COLLECTING_MSG >::value,
               mutable_msg< messages_collected_t >,
               messages_collected_t >
            ::type;

   public :
      //FIXME: what about message tracing traits?
      templatetypename... ARGS >
      mbox_template_t(
         mbox_id_t mbox_id,
         ARGS &&... args )
         :  specific_base_type( mbox_id, std::forward<ARGS>(args)... )
         {
            details::check_mutability_validity_for_target_mbox<config_type>(
                  this->m_target );
         }

PS. Ну и еще наброшу на тему C++ных шаблонов. Когда ими реально упарываешься, то начинаешь совсем по другому относиться к спорам на тему того, что вместо C++ можно использовать plain old C или Rust. Программирование на шаблонах C++ -- это, блин, совсем другой подход к программированию. Ни Rust, ни, тем более, C, тут и рядом не стояли. Т.е. сделать одно и тоже можно будет на разных языках, но это будут совершенно разные решения, абсолютно не похожие на друг друга.

вторник, 4 июля 2017 г.

[prog.c++] Новая большая статья про SObjectizer на Хабре

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

Статья получилась большой, материала в ней много. Но старались сделать доступной и понятной. Если что, то с удовольствием ответим на вопросы в комментариях.

Темы для следующих статей принимаются :)

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

суббота, 1 июля 2017 г.

[life.cinema] Очередной кинообзор (2017/06)

Незаметно пролетел июнь и пришло время очередного кинообзора. Традиционно в начале списка идут фильмы, которые понравились больше. Ну а замыкают список те фильмы, которые не понравились.


Таинственный город Z (The Lost City of Z, 2016). Хороший фильм, мне понравился. Может быть в каких-то моментах он был слегка нудноват и не динамичен. Но это итоговое впечатление не испортило. Тем не менее, подозреваю, что сама по себе история про увлеченного путешественника будет интересна не всем.

Меч короля Артура (King Arthur: Legend of the Sword, 2017). Качественно снятое фэнтези. Гай Ричи не подкачал. Перед просмотром у меня было скептическое отношение из-за негативных отзывов о фильме, которые доводилось читать. Но для своего жанра получилось весьма достойно.

Мумия (The Mummy, 2017). Хороший развлекательный аттракцион. Правда, я лично не понял двух вещей. Во-первых, зачем там Том Круз в главной роли. Ни он в фильм ничего не привнес, ни фильм ему ничего не дал. От участия Круза ждешь чего-то большего, но здесь ничего "эдакого" не было. Во-вторых, зачем нужно было сюда вплетать еще и историю Джекила и Хайда. В общем, сходить и развлечься можно, но не более того.

Киллер поневоле (Un petit boulot, 2016). Понравилось. Вот просто понравилось и все.

Эксперимент "Офис" (The Belko Experiment, 2017). Вообще такого рода фильмы мне нравятся. Здесь же явно ощущалось, что бюджет у картины был более чем скромным, однако несколько постаревших актеров, чей звездный час уже давно в прошлом, смогли удержать фильм на вполне себе достойном уровне.

Жмот (Radin!, 2016). Любопытный фильм. Как комедия он меня не сильно зацепил (хотя и придраться не к чему). Но зато показалось, что Дэни Бун очень хочет сменить амплуа комика на амплуа серьезного драматического актера. И что таланта для этого у него вполне может хватить.

Ограбление в Хаттон-Гарден (The Hatton Garden Job, 2017). Сразу скажу, что снято так себе. Но есть в нем какой-то английский стиль, который добавляет фильму какого-то непонятного очарования и заставляет смотреть даже не смотря на неторопливое развитие событий и отсутствие каких-то эффектных сцен.

Его собачье дело (Once Upon a Time in Venice, 2017). Не шедевр, но посмотреть вполне можно, особенно если шутки "пониже пояса" не смущают.

Возьми меня штурмом (Raid dingue, 2016). Типичная французская комедия. Сильно предсказуемая, местами смешная. Мне особенно понравилось то, что Дэни Бун вообще не кривлялся, и то, как Иван Атталь сыграл эксцентричного злодея.

Калифорнийский дорожный патруль (CHIPS, 2017). Обычная американская комедия. Не шедевр, но и не полный шлак. Можно посмотреть, но и ждать чего-то выдающегося не стоит.

Трансформеры: Последний рыцарь (Transformers: The Last Knight, 2017). Все деньги на экране и это видно, к визуальной составляющей вообще никаких претензий. Но вот все остальное находится где-то по ту сторону добра и зла. Такое ощущение, что Майкла Бэйя настолько утомила вся эта история с трансформерами, что он сам для себя решил: "Ну раз вы просите, то я вам сниму такое, что вы сами не будете рады, что упросили меня." Вот он и снял так, что смотреть это могут разве что дети до 10 лет.

Еще я тут пересмотрел фильм "Эверест" от 2015-го года. Как-то в этот раз он зашел гораздо лучше. Может быть потому, что в этот раз я уже не обращал внимания на то, как снято. Зато следил за тем, о чем рассказывает кино. В итоге поменял свое мнение о фильме на гораздо более лучшее. Достойное кино, как по мне.

вторник, 27 июня 2017 г.

[prog.c++] Практически динамически-типизированное программирование

Давеча, занимаясь примером для демонстрации Asio-инфраструктуры для SObjectizer из нового проекта so_5_extra, написал фрагмент C++кода, в котором практически не фигурировали имена конкретных типов. Буквально возникло впечатление, что программирую на каком-то динамически-типизированном языке (правда, с излишне многословным синтаксисом). Кому интересно посмотреть немного C++14-того хардкора милости прошу под кат.

понедельник, 26 июня 2017 г.

[prog.c++] so_5_extra-1.0.0 и so-5.5.19.2

Мы выпустили первую версию своего нового проекта поверх SObjectizer -- so_5_extra версии 1.0.0.

В этой версии в so_5_extra доступны:

  • so_5::extra::env_infrastructures::asio::simple_not_mtsafe -- реализация однопоточной инфраструктуры SObjectizer-а на базе Asio. Т.е. с использованием этой инфраструктуры и Asio, и SObjectizer смогут работать на одной и той же рабочей нити;
  • so_5::extra::mboxes::round_robin -- специальный mbox, который доставляет сообщения поочередно каждому из N агентов, подписанных на это сообщение;
  • so_5::extra::shutdowner -- небольшой инструмент для упрощения операции завершения работы в больших приложениях.

Исходники можно взять либо из репозитория, либо загрузить из соответствующего раздела.

Документацию по проекту можно найти в Wiki. Если из документации чего-то не понятно или что-то в ней не описано, то не сочтите за труд, дайте нам знать. Улучшим, расширим и углубим :)

Проект header-only. Если захочется собрать тесты и примеры самостоятельно, то придется воспользоваться Ruby и Mxx_ru. Зависимости так же подтягиваются через MxxRu::externals. Но в секции Files есть архивы с именами вида so_5_extra-1.0.0-full.tar.xz, в которых уже все зависимости присутствуют. Поэтому можно брать *-full.tar.xz архив, распаковывать, прописывать в INCLUDE путь к so_5_extra-1.0.0/dev и пробовать.

Работоспособность проверялась под Linux-ом (gcc 5.4 и 7.1, clang 3.7 и 4.8) и Windows (gcc 5.2-7.1, VC++ 14.0 и 15.0). На всякий случай выставлять -Werror при работе с so_5_extra не советуем, т.к. и gcc, и clang очень сильно ругаются на потроха Asio.

В планах у нас добавление еще нескольких фич в so_5_extra. Следующие версии будут выходить по мере добавления новых фич. В том числе в планах и simple_mtsafe-инфраструктура для Asio, но приоритет у этой задачи не самый высокий. Если кому-то нужна thread-safe реализация Asio-инфраструктуры для SO-5, то дайте знать. Постараемся повысить приоритет.

Обращаем внимание, что so_5_extra распространяется под двойной лицензией: GNU Affero GPL для OpenSource применения, и коммерческая лицензия для использования в закрытых проектах. Если кому-то интересна коммерческая лицензия, то пишите на info at stiffstream dot com, там цена вопроса порядка $40 за одного разработчика в год.

Попутно мы сделали SObjectizer-5.5.19.2, в который вошло несколько фич, необходимых для реализации so_5_extra. Дистрибутивы SObjectizer лежат там же, где и обычно.

пятница, 23 июня 2017 г.

[prog.c++.flame] Взять бы, да и закрыть Boost...

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

Вот просто взять и закрыть. Что вошло в Boost, то пусть там и остается.

А вот всем остальным нужно учиться жить без Boost-а.

Поскольку языку программирования нужна не одна мегабиблиотека, в которую пытаются впихнуть все. А нормальный. Повторяю, нормальный, Карл!, способ подтаскивания в свой проект сторонних библиотек. Но пока есть Boost, и пока попадание в Boost является целью для многих разработчиков библиотек, эволюция и селекция нормальных способов управления зависимостями в C++ идет черепашьими темпами.

Да и смысл Boost-а в настоящее время от меня ускользает. 17 лет назад Boost был полигоном для обкатки того, что хотелось бы включить в стандарт. Boost.Thread, Boost.SharedPtr, Boost.Optional и все такое. Ну OK, тогда это было актуально, когда работа над стандартами C++ велась не слишком быстро.

Но сейчас-то? Какой смысл в Boost-е кроме как в централизованной сборке относительно небольшого количества C++ных библиотек, которые совместно тестируется перед релизом? Ну кроме протекционизма?

Кстати о протекционизме. Вот есть в Boost-е библиотеки Boost.Test, Boost.Log, Boost.Format. Для которых существуют не менее достойные, мягко говоря, аналоги в виде Catch, Spdlog и Fmtlib. С какой стати старые и неудобные монстры, вроде Boost.Test и Boost.Log, должны иметь преференции в современном мире перед теми библиотеками, которые в Boost не входят? Ведь не так уж и редко от сторонних аналогов люди отказываются потому, что дальше Boost-а и не заглядывают. Но даже если и заглядывают, то иногда предпочитают Boost, потому что Boost к проекту уже подключен, а подтаскивание еще одной библиотеки в C++ный проект -- это боль для многих.

В общем, Карфаген должен быть разрушен Boost сделал свое дело, Boost должен уйти.

PS. Пост написан под влиянием боли, которая появляется, когда в зависимостях кросс-платформенного проекта оказывается достаточно свежая версия Boost-а.

четверг, 22 июня 2017 г.

[prog.c++] Если разрабатывать REST-сервисы на C++, то как должен выглядеть "инструмент мечты"?

Допустим, вам нужно разработать RESTful сервис на C++. Не будем сейчас вступать в религиозные споры на тему того, зачем, когда и кому в здравом уме это может потребоваться. Ну мало ли ;) Может нужно выставить REST API для старого легаси-кода, которому 20 лет и который никто с C++ переписывать не будет. Может нужна высокая эффективность и низкое потребление ресурсов. Может нужно сделать это для военки на Эльбрусах какой-то экзотической платформы, для которой нормального качества компиляторы есть только для C и C++. Может еще что-то, включая упоротость и мазохизм :)

Итак, вы стоите перед выбором, как же сделать REST API на C++. В какую сторону вы будете смотреть? Напишете все сами или постараетесь взять что-то готовое?

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

Если будете выбирать согласно своих требований, то что вы в свой список требований включите обязательно? Что будет однозначно положительными факторами в пользу стороннего решения? А что однозначно отрицательным?

Может вы уже используете что-то и вас в этом что-то сильно не устраивает? Что?

Понимаю, что вопросов много. Но почему бы не пофантазировать и не пообщаться о том, как оно должно было бы быть в идеальном мире C++? :)

понедельник, 19 июня 2017 г.

[prog] Проблема нумерации: so_5_extra-5.5.19-1.0 или so_5_extra-1.0-5.5.19 или...?

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

У нас на финальную стадию подготовки к релизу вышла дополнительная библиотека для SObjectizer-а под названием so_5_extra. Сейчас в нее входят три компонента: однопоточный вариант SObjectizer Environment на базе Asio (немного об этом здесь), готовая реализация round-robin mbox-а и специальная штука под названием shutdowner, которая предназначена для обработки некоторых сценариев завершения больших приложений. Со временем состав so_5_extra будет еще расширяться, но для первого релиза нам показалось достаточно этих трех. Все это уже работает и протестировано, но нужно еще написать какую-то вводно-обзорную документацию.

Неожиданной сложностью оказался выбор системы нумерации версий для so_5_extra. Традиционный semver, вроде so_5_extra-1.0.0, здесь не очень подходит потому, что версии so_5_extra планируется плотно синхронизировать с версиями SObjectizer-а. Поскольку so_5_extra в своей реализации очень активно использует знание того, что и как выполняется в конкретной версии SObjectizer. Поэтому версия so_5_extra-1.0.0, которая была сделана для SObjectizer-5.5.19, не обязательно будет работать с SObjectizer-5.5.18 или SObjectizer-5.5.20. В обратном направлении, кстати, тоже работает. SObjectizer так же допиливается под нужды so_5_extra. Например, вместе с первой версией so_5_extra мы опубликуем и SObjectizer-5.5.19.2, в который добавлено несколько фич для работы so_5_extra.

Поэтому хочется иметь какую-то систему нумерации, в которой номера версий so_5_extra были каким-то боком увязаны друг с другом. Но, при этом, чтобы допускалась некоторая свобода. Например, может быть so_5_extra-1.0.0, которая выпущена для SO-5.5.19.2, но затем появляется SO-5.5.19.3, из-за которой менять номер для so_5_extra не нужно. С другой стороны, может быть so_5_extra-1.0.1, ради которой не нужно менять номер версии SO-5.5.19.2.

В результате я сейчас всерьез рассматриваю следующие варианты системы нумерации:

  1. so_5_extra-5.5.19-1.0. С тем, чтобы впоследствии можно было использовать номера вида so_5_extra-5.5.19-1.0.12, so_5_extra-5.5.19-1.2.39, so_5_extra-5.5.20-1.0 и т.д. Тут, правда, возникает вопрос: как между собой соотносятся, скажем so_5_extra-5.5.19-1.2.39 и so_5_extra-5.5.20-1.0.0? На который у меня пока ответа нет;
  2. so_5_extra-1.0-5.5.19. С последующим развитием в сторону so_5_extra-1.2.39-5.5.19, so_5_extra-2.0-5.5.19 и т.д.
  3. Просто тупо совместить нумерацию so-5 и so_5_extra. Т.е. если есть so-5.5.19.2, то и есть so_5_extra-5.5.19.2. Если есть so_5_extra-5.5.20.34, то есть и so-5.5.20.34. Хотя этот вариант мне нравится меньше всего.

Посему вопрос к читателям: что вас меньше испугает и запутает? so_5_extra-5.5.19-1.0.0 или so_5_extra-1.0.0-5.5.19?

понедельник, 12 июня 2017 г.

[business.book] Кратко о книге "Великие по собственному выбору" Джима Коллинза и Мортена Хансена

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

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

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

Завершающие 100 страниц -- это рассказ о том, как само исследование проводилось. Эту часть книги я не читал, только слегка просмотрел. Как по мне, завершающая треть книги может быть интересна только тем, кто сам собирается провести какое-то подобное исследование.

Мои впечатления следующие:

  • первые 2/3 книги читаются легко и интересно, много примеров из разных областей. Воды не много, хотя и не обошлось без типичной англосаксонской манеры неоднократно повторять одно и то же на разные лады. Так что если ничего из Коллинза раньше не читали, смело можно взять и познакомиться с творчеством автора;
  • некоторые моменты, о которых лично я имел несколько другое мнение, заставляют задуматься о том, а насколько вообще авторы книги понимают специфику определенных прикладных областей и правильно ли они интерпретируют обнаруженные ими в процессе исследования факты. Например, рассказ о том, как Microsoft относилась к разработке OS/2 для IBM и как Microsoft "подстраховалась" от рыночной неудачи OS/2 продолжая работу над своей ОС Windows. Если читатель более-менее в курсе истории отношений Microsoft-а и IBM, а так же в курсе истории развития OS/2 и причин неудачи OS/2 на рынке, то у него могут возникнуть возражения против точки зрения авторов книги (у меня, например, возникли). Соответственно, ловишь себя на мысли, что есть есть несостыковочка здесь, то может она не одна такая? И насколько тогда можно доверять выводам авторов?
  • у меня сложилось ощущение, что ключевыми факторами, на которых авторы книги пытались заострить внимание читателей, являются: здравый смысл, последовательность и дисциплина. Что очень сильно, на мой взгляд, пересекается с ключевыми факторами из "Живой компании" Ари де Гиуса. А раз так, то смело можно обойтись чтением "Живой компании" вместо "Великие по собственному выбору".

Так что, если вы пока еще не прочитали "Живую компанию" и, например, "Управление жизненным циклом корпорации" Ицхака Адизеса, то лучше сперва прочесть эти две книги, а не "Великие по собственному выбору". Ну а если это все уже прочитано, но хочется прочитать что-нибудь именно из Коллинза, то тогда можно и "Великие по собственному выбору" осилить. Хуже точно не будет.

PS. Кажется, читая про Zappos и про Twitter, встречал упоминания о Джиме Коллинзе как о "гуру" от бизнеса и менеджмента, репутация которого базируется на успехе книг "Построенные навечно" и "От хорошего к великому". Но вот я прочел уже вторую его книгу и мне сложно понять, почему Коллинз считается таковым "гуру".

суббота, 10 июня 2017 г.

[prog.c++] В очередной раз про Rust. О том, почему до сих пор меня Rust не прельстил

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

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

Сам я пока в Rust всерьез не вложился и причины тому вовсе не какие-то идеологические, а весьма прозаические. Мы с коллегами пытаемся создать бизнес вокруг инструментария для программистов. Что именно начнет приносить нам деньги -- продажа продуктов, продажа коммерческих лицензий, обучение, консалтинг, заказная разработка или что-то другое -- это выяснится со временем. Поскольку у нас большой опыт в C++, то сейчас мы концентрируемся именно на инструментарии для C++. Ибо здесь есть рынок: по некоторым оценкам количество C++ разработчиков в мире насчитывает более 3 миллионов человек, накоплена огромная кодовая база на C++, которая никогда не будет переписана на других языках, да и новые проекты на C++, пусть не часто, но начинают (и выбор C++ в качестве языка реализации нового проекта в современных условиях вполне имеет смысл). Так что в области C++ есть и какой-никакой рынок, и нам есть что на нем предложить.

А вот для Rust-а такого рынка, насколько я могу судить, пока еще нет. Вроде как есть какой-то совсем небольшой спрос на Rust-разработчиков, но вряд ли сейчас найдется много желающих покупать коммерческие библиотеки для Rust-а, или коммерческие лицензии на такие библиотеки. Да и вряд ли кто-то будет готов платить за консультации по Rust-у или за обучение Rust-у разработчиков, переходящих на Rust с других языков программирования. Думаю, что не ошибусь, если скажу, что не смотря на весь хайп вокруг Rust-а, реальное присутствие Rust-а в коммерческой разработке ПО в мире находится где-то на уровне статпогрешности. Посему достаточно емкого рынка инструментария для Rust-а еще просто нет. Может через 3-5 лет такой рынок сложится и достигнет достаточного объема, чтобы на нем можно было бы зарабатывать. Но сейчас это не так.

Ну а поскольку самый дефицитный ресурс -- это время, то я пока не вижу смысла тратить этот ресурс на Rust, если его можно потратить на что-то с более реальными перспективами продажи. И это, наверное, главная причина, почему мы до сих пор не вложились в Rust. Хотя из поля зрения его и не выпускаем.

Но сегодня я бы хотел затронуть еще один аспект. Он касается того, насколько сильно придется перестраивать мозги старому C++нику, вроде меня, при переходе с C++ на Rust. И будет ли такая перестройка того стоить.

среда, 7 июня 2017 г.

[prog.c++] Жалел ли кто-нибудь об отсутствии Erlang-style супервизоров в SObjectizer?

Вопрос к тем читателям блога, которые в какой-то мере интересуются SObjectizer-ом: возникало ли у вас при знакомстве с SObjectizer-ом сожаление о том, что в SObjectizer-е нет механизма супервизоров, как в Erlang-е?

Вопрос вызван тем, что сейчас дополнительный проект so_5_extra, который мы хотели бы зарелизить в этом месяце, наполняется функциональностью. Наш интерес состоит в том, чтобы добавить в so_5_extra вещи, которые бы были востребованы потенциальными и актуальными пользователями SObjectizer-а. Если кому-то в SObjectizer не хватает Erlang-овых супервизоров, то мы могли бы их реализовать в so_5_extra вне зависимости от моих персональных взглядов на этот счет.

Ну а если никому не нужны, то "раз врач сказал в морг, значит в морг" :) Все-таки работа с небезопасным C++ сильно отличается от работы с безопасным Erlang-ом.

PS. Здесь можно высказать любое соображение касательно того, чего не хватает в SObjectizer. Или что хотелось бы видеть сделанным по-другому.

PPS. Сейчас в so_5_extra уже есть однопоточная инфраструктура, позволяющая запустить SO-5 с использованием Asio в качестве бэкэнда. В варианте simple_not_mtsafe. Кстати, нужна ли кому-нибудь такая же инфраструктура в варианте simple_mtsafe или инфраструктура, которая позволяет использовать Asio-бэкэнд при работе Asio на пуле потоков? Так же в so_5_extra уже есть реализация round-robin mbox-а. Пока мы закрываем ряд юридических вопросов вокруг so_5_extra, есть возможность включить в so_5_extra еще что-нибудь полезное. Например, те же самые супервизоры, если они кому-то нужны.

понедельник, 5 июня 2017 г.

[prog.thoughts] Внезапное осознание момента в модели publish/subscribe и топиков с wildcard-ами в именах.

Внезапно поймал себя вот на чем: есть publish/subscribe, которая доступна посредством разнообразных MQ-шных брокеров (т.к. IBM WebSphere MQ, RabbitMQ или mosquitto). Там можно подписываться на топики, в именах которых есть wildcard-ы (спецсимволы вроде +, * и #). Например, кто-то публикует сообщение в топике с именем /temperature_sensors/floor/1/n001/value. А приходит это сообщение к тем, кто подписался на топики /temperature_sensor/floor/+/+/value и /temperature_sensors/floor/#.

Так вот, внезапно осознал, что в 90% случаев (а может и в 99.9%) при использовании wildcard-ов нужно иметь точное имя топика, в котором сообщение опубликовано. Т.е. в 90% случаев нужно не только уметь подписаться на /temperature_sensors/floor/+/+/value, но нужно еще обязательно вместе с сообщением получить и имя топика (будь то temperature_sensors/floor/1/n001/value или temperature_sensors/floor/10/n100_10_03/value). Без знания точного имени нет пользы от самого лишь сообщения из топика.

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

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

пятница, 2 июня 2017 г.

[prog.thoughts] Пара докладов про управление зависимостями в C++ и небольшое послесловие к ним

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

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

Мне же, однако, подходы на базе централизованых хранилищ пакетов, будь то conan.io (в ближайшем будущем conan-central), hunter или cppan.org не очень нравятся. Точнее говоря, я не верю, что это окажется достаточно жизнеспособным из-за разных причин. Во-первых, в C++ все очень разобщено, поэтому слабо верится в то, что народ массово начнет концентироваться вокруг какого-то одного центрального репозитория C++ных проектов. Во-вторых, кто и с какой радости должен будет оплачивать сей банкет? Хостинг 100500 непонятных проектов и кучи версий для них -- это накладные расходы, которые кто-то должен оплачивать. Что-то в мире C++ мне не видится организации, которая взяла бы на себя бремя этих накладных расходов. Тем более, что почти что все уже живет на ресурсах типа GitHub, BitBucket или SourceForge.

Кроме того, те же Conan и Hunter работают по принципу организации центрального хранилища загруженных пакетов на машине разработчика. Т.е., если разработчик однажды скачал себе Boost-1.64 для проекта A, а затем захотел использовать Boost-1.64 для проекта B, то пакетный менеджер будет переиспользовать уже загруженный ранее Boost.

Как по мне, то этот подход хорош для быстрой разработки какой-нибудь мелкой программулины. Ну, например, прочитал я на Хабре какую-то статью и захотелось мне проверить один из ее тезисов. Или задали на LOR-е вопрос, для поиска ответа на который нужно написать программку на 50 строк. В этих случаях хочется приложить минимум усилий: где-то просто перечислить список нужных мне внешних зависимостей (например, таких, как Boost, ICU, zlib) и потратить минимум времени на подгрузку и сборку этих зависимостей. Поскольку, если я пишу программу на 50 строк "на выброс", то мне вряд ли захочется ждать, пока Boost еще раз скачается и скомпилируется. Поэтому переиспользование того, что было загружено ранее, в таких условиях -- это вполне себе разумный подход.

С другой стороны, когда я делаю какой-то внутренний проект (или же работаю с какой-то приватной веткой), то у меня могут возникать ситуации, когда мне нужно взять не просто библиотеку X, а конкретный ее слепок. Скажем, библиотека X разрабатывается моим коллегой и он добавил в X новый нужный мне функционал, но еще не зафиксировал ее стабильную версию. Поэтому я на свой страх и риск хочу взять X от ревизии (коммита) R1. С большой долей вероятности я могу наткнуться в X@R1 на какую-то проблему. Из-за чего мне потребуется перейти на X от ревизии R2 (может быть даже эту ревизию я создам сам для того, чтобы исправить проблему, а потом вернуть правки в основную ветку разработки X).

В этих случаях, как мне кажется, плохо работают обе составляющие централизованного подхода (положенного в основу canon/hunter/cppan):

  1. Центральное хранилище опубликованных пакетов. Поскольку для работы с X@R1 кто-то должен быть создать соответствующий пакет и опубликовать его в этом хранилище. Потом это же нужно будет проделать с X@R2 и т.д. При том, что вряд ли хорошо засирать центральное хранилище промежуточными пакетами. Как и делать собственное зекало этого центрального хранилища для того, чтобы засирать его локально.
  2. Централизованное хранилище загруженных на локальную машину пакетов. Поскольку если X@R1 и X@R2 мне нужны только для проекта Y, да и то в какой-то временной ветке Y, то не есть хорошо сохранять X@R1 и X@R2 там же, где хранятся нормальные стабильные версии чего-то вроде Boost-а или ICU.

Имхо, для таких случаев хорошо работает подход, который мы используем в своем MxxRu::externals:

  • во-первых, MxxRu::externals сам забирает исходники стороннего компонента оттуда, где эти исходники лежат. Например, лежит Boost в tar.bz2 на SourceForge -- оттуда его и заберем. А исходники spdlog от конкретного коммита есть в git-е на GitHub-е -- ну значит вытянем их через git с GitHub-а. Таким образом для того, чтобы сделать свой пакет доступным для пользователей, не нужно предпринимать каких-то серьезных усилий. Можно даже свой тарбол не делать, если кроме GitHub-а ни на что мозгов не хватает, то достаточно просто теги в своем репозитории создавать, GitHub сам для них тарбол доступным для загрузки сделает. Ну а если нужно забирать какие-то промежуточные версии собственных компонентов из закрытых репозиториев внутри своей организации, то тут вообще никаких проблем нет, ничего дополнительно поднимать не нужно (речь про локальный инстанс того же Conan-а);
  • во-вторых, загруженные зависимости кладутся только в локальный рабочий каталог. Поэтому, если моему проекту Y потребовался сперва X@R1, а затем X@R2, то исходники X@R1 и X@R2 никуда за пределы рабочего каталога Y не уйдут. И, соответственно, когда я удалю этот рабочий каталог, то автоматически исчезнет и весь "мусор" , который был с этим связан.

Однако, поскольку мир сходит с ума и куча народа с удовольствием жрут тот же самый CMake, то есть серьезные подозрения, что CMake в качестве системы сборки и пакетные менеджеры на его основе (вроде Conan-а и Hunter-а) таки станут де-факто стандартом в мире C++. Ну что тут поделать, количество разума -- величина постоянная, а население-то растет.

ЗЫ. Отдельно хочется помянуть незлым тихим словом красноглазых Linux-оидов, которые всерьез считают, что для управления C++зависимостями нужно пользоваться штатным пакетным менеджером вашего любимого дистрибутива Linux-а. Этих сторойными рядами прямо направляю в жопу. Ибо ваше мнение не интересно. Ну вот от слова совсем. По крайней мере пока не поймете, что "кроссплатформенность" -- это "переносимость между разными платформами", а не "переносимость между разными дистрибутивами Linux-а".

четверг, 1 июня 2017 г.

[prog] Очередная статья про SObjectizer для Хабра: будет ли интересен разбор примера machine_control?

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

Собственно, почему может быть интересно подробнее описать этот пример? Потому, что в нем задействованы почти все самые важные фичи SObjectizer-а. Включая и возможность создания агентов-шаблонов. И хотя пример остается все-таки абстрактным (имитация она и есть имитация), но он совсем не игрушечный, в отличии от ping-pong-а или обедающих философов. Хотя бы чуть-чуть, но приоткрывающий завесу над тем, как на SObjectizer выглядит более-менее приближенный к реальности код.

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

В общем, если кому-то интересна такая статья, то дайте об этом знать: либо в комментариях, либо через +1 в G+, либо через лайки в FB и LinkedIn (где я размещу ссылки на этот пост).

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

среда, 31 мая 2017 г.

[life.cinema] Очередной кинообзор (2017/05)

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

Золото (Gold, 2017). Очень хорошо сделанная драма. Но главное -- это досмотреть до самого финала. Тогда некую неторопливость развития событий можно будет полностью простить.

Пираты Карибского моря: Мертвецы не рассказывают сказки (Pirates of the Caribbean: Dead Men Tell No Tales, 2017). Прекрасный образец того, как нужно делать развлекательный киноаттракцион: выключаешь мозги, откидываешься в кресле и понеслась! Ну и да, все деньги на экране, и это видно.

Перестрелка (Free Fire, 2016). Фильм специфический, наверняка понравится не всем. Но я получил большое удовольствие от просмотра.

Берлинский синдром (Berlin Syndrome, 2017). Ну очень неторопливо. Иногда хочется включить его на 1.25 или 1.5 скорости. Однако, именно неторопливость помноженная на предельную обыденность и составляет в итоге уникальную, тягостную, но сильную атмосферу этой картины.

Три для до весны (2017). Понравилось, как снято. Для российского кинематографа более чем достойно. Хотя в сюжетной линии с главным злодеем НКВД-шником авторы перестарались.

Без тормозов (À fond, 2016). Незамысловато, местами туповато, но смешно и весело.

Столик №19 (Table 19, 2017). Хорошая смесь специфического юмора, из-за которого нужно внимательно ловить каждую реплику, и сентиментальной драмы. Сдобренной отличной актерской игрой и работой оператора.

Похищение (Kidnap, 2017). Добротно. Хороший напряженный триллер.

Ирис (Iris, 2016). В целом неплохо. Но правда не понял, за счет чего: сюжета или присутствия красивой актрисы в главной роли ;)

Семейное ограбление (Mes trésors, 2017). Нормальная французская комедия. Не шедевр, но и потраченного времени не жалко.

Комик (The Comedian, 2016). Фильм можно смотреть, если нет неприятия стендапа вообще и жесткого пошлого юмора в частности.

Время псов (The Hunter's Prayer, 2017). Странная картина. Вроде бы актеров подобрали. Вроде как динамику создали. Вроде как и постреляли вдоволь. А вот не торкает особо.

Мелкие преступления (Small Crimes, 2017). Ждал большего. Фильм оставил впечатление какого-то сумбура, в котором события активно переплетаются, но непонятно почему и из-за чего. Хотя нужно начислить дополнительные очки за отсутствие хэппи-энда.

Пробуждение Зодиака (Awakening the Zodiac, 2017). Довольно посредственно. Хотя посмотреть можно, только не нужно ждать ничего, хотя бы отдаленно напоминающего замечательный "Зодиак" Дэвида Финчера от 2007-го года.

Лжец, Великий и Ужасный (The Wizard of Lies, 2017). Пример того, как авторы взяли потенциально очень крутую тему, но не смогли донести до зрителя ощущение того, что главный герой фильма повинен в создании самой большой финансовой пирамиде в истории.

Кухня. Последняя битва (2017). Средней руки российская комедия. Местами смешная. С отличной картинкой. Белорусской аудитории отдельно сильно понравится маленький проезд по "Коленьке".


Ну а эти две картины находятся просто вне всякой критики, т.к. днище было пробито с огромной силой и на невероятную глубину.

Чужой: Завет (Alien: Covenant, 2017). Это так плохо и маразматично, что я даже не могу увязать этот фильм с первыми тремя "Чужими". Ну вот есть уникальная вселенная "Чужих", показанная в первых трех фильмах. Ее даже не смогли испортить странной четвертой частью. А "Прометей" и "Чужой: Завет", особенно "Чужой: Завет", ну никак у меня не увязываются со знаменитой серией. Это какое-то совсем другое кино, совсем про других монстров и совсем про других людей. Можно было бы о "Чужом: Завет" порассуждать именно как о совершенно другой истории. Но происходящее на экране настолько тупо и неинтересно, что нет смысла это делать.

Форсаж 8 (The Fate of the Furious, 2017). Это какой-то красочный киноаттракцион, но непонятно для какой аудитории. Может быть для 10-летних детей. Как это можно всерьез смотреть взрослым людям просто не представляю.

вторник, 30 мая 2017 г.

[flame] Образ современного ИТ-шника в РБ: "это молодой человек, владеющий иностранным языком, ..."

Цитата из официоза про встречу руководства моей альма-матер с представителями ИТ-шных компаний города:

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

Показательно, что владение иностранным языком поставлено на первое место в списке необходимых навыков.

Пожалуй, это все, что нужно знать про развитие ИТ в РБ.

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

  1. Отсутствие своей продуктовой разработки как класса. Т.е. единичные примеры как были, так и будут. Но именно что единичные.
  2. Уровень зарплат аутсорсеров на глобальном мировом рынке будут определяться не столько уровнем зарплат в странах, откуда идет заказ на аутсорс, сколько уровнем зарплат в развивающихся странах, которые уже пытаются урвать свою долю пирога, а так же тех, которые только собираются это сделать. Имхо, глупо ожидать, что желающие "войти-в-Ойти" на Филиппинах, во Вьетнаме или в Индонезии будут знать английский хуже, чем студенты провинциальных белорусских ВУЗов.

Итого, как мне видится дальнейшее развитие истории:

  • хорошо, если государство будет заинтересовано в экспорте жопочасов местных ИТ-шников. Ну, такая же статья экспорта, как и калийные удобрения. Только ресурсы здесь остаются и, благодаря своим деньгам, хоть как-то оживляют внутренний рынок товаров и услуг. Как-то страшно думать, во что это все превратится, если государство таки решит зарезать курочку, ибо кушать ну очень хочется, а ее и так слишком долго жалели;
  • поскольку основной вид деятельности в местном ИТ -- это аутсорс, то желающим "войти-в-Ойти" и чувствовать себя там нормально, прежде всего нужно делать упор на изучение иностранных языков (лучше нескольких). А так же на развитие soft skills и грамотной продажи самого себя. Умение программировать из года в год будет становиться все менее и менее важным профилирующим навыком. В том числе и потому, что само массовое программирование все больше и больше требует умения быстро склеить что-то из уже готовых компонентов, нежели знаний и способностей создать что-то новое и нетривиальное. Кроме того, в аутсорс же отдается не только программирование, но и куча сопутствующих активностей: бизнес-аналитика, тестирование, управление проектами, техническая документация, как минимум. Тут умение программировать вообще не обязательно;
  • уровень привлекательности ИТ-отрасти в плане доходов будет определяться коньюктурой мирового рынка. Не хочу сказать, что ЗП в отрасли упадут вот прямо завтра или послезавтра. Но то, что когда-нибудь это произойдет, поскольку ту же самую работу вполне себе хорошо будут делать юноши и девушки из Вьетнама или Венесуэлы, но стоить это будет в 10 раз дешевле, и тогда никакие способности, установившиеся связи и имеющийся опыт не сделают белорусских ИТ-шников настолько ценными, чтобы платить нам в 10 раз больше. На глобальном-то рынке. Так что современным молодым людям, владеющим иностранными языками, и зарабатывающим по паре-тройки тысяч долларов в месяц, полезно помнить, что этот уровень зарплат обеспечивается не какими-то их уникальными особенностями. А вот такой нынешней ситуацией на рынке.

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

пятница, 26 мая 2017 г.

[flame] Егор Бугаенко в DevZen подкасте (послешоу)

Дослушал таки послешоу подкаста DevZen, в котором участвовал Егор Бугаенко. Впечатления сильно двойственные.

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

В принципе, здесь я услышал то, что и рассчитывал услышать. Стало лучше понятно, что за компания у Бугаенко. Появилось впечатление, что это даже не классический аутсорсинг. Это, скорее, какой-то маленький маркетплейс для фрилансеров. Только особенность этого маркетплейса в том, что он находится под жестким модерированием создателя, т.е. самого Егора Бугаенко. Он приносит на маркетплейс заказы (окучивая потенциальных заказчиков), он же запускает или выгоняет с этого маркеплейса фрилансеров. Но суть, как мне показалось, именно в том, что под Бугаенко есть некая маленькая биржа труда, на которую с одной стороны вываливаются задачи, а с другой пасутся прикормленные и отдрессированные исполнители.

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


А вот то, что началось где-то с 50-й минуты или позже, когда речь пошла о тенденциях, о менеджменте, о будущих продуктах-платформах, как будто совсем другой человек начал говорить. Как будто вместо здравомыслящего практика микрофон взял совершенно упоротый маркетолог. Тут начались такие же подтасовки и передергивания, как и в рассказах Бугаенко про ООП.

Дабы не быть голословным, приведу несколько высказываний и кратко прокомментирую, почему я с ними не согласен.

  • "Не будут нанимать фрилансера с соседней улицы". Речь шла о том, что ситуация меняется и наступает время, когда нанимать будут не по знакомству или по соседству, а исходя из рыночных реалий. Мол, если такой же спец есть в Китае за меньшие деньги, то брать соседа в Сан-Франциско не будут. Отчасти это так, но все не так просто. Даже не будем рассматривать основную причину, т.е. неравенство доходов в разных концах мира. Ситуация станет сильно другой, когда за одну и ту же работу в США и в Малайзии начнут платить сравнимые деньги. Но есть еще такая вещь, как репутация. Нанять фрилансера в Интернете вовсе не значит гарантировать себе результат. По факту может быть такое, что дешевле было бы нанять соседа задорого, но быть уверенным в том, что работа будет сделано качественно и в срок. В принципе, за примерами далеко не нужно ходить. На рынке стоматологических услуг уже не первый десяток лет услуги предлагают и одиночки, и мелкие кабинеты, и небольшие поликлиники и большие клиники. Только вот мы же не бежим к самому дешевому врачу. Или, скажем, если вам приходилось сталкиваться с ремонтом и вы хотели найти хорошего плиточника, вы же не выбирали самое дешевое предложение в газете частных объявлений. Да и сам Бугаенко признался, что клиенты к нему приходят из-за его репутации, хотя услуги его компании, по его же словам, обходятся недешево. Так что этот тезис ну очень спорен. Хотя с тем, что рынок становится глобальным, и что конкурировать нужно будет с поставщиками таких же услуг из разных концов света, спорить не приходится, это уже свершившийся факт;
  • "Над ними стоит менеджмент, который ничего не делает". Речь про то, что работу работают узкие специалисты (вроде программистов или продавцов), а менеджмент просто паразитирует на их работе. Ну тут можно только посочувствовать человеку, который сталкивался только с таким менеджментом. Дебилы, лентяи, карьеристы и просто случайные люди встречаются везде. И среди программистов, и среди менеджеров. Конечно, когда менеджером становиться дебил-карьерист, то последствия могут быть тяжелыми. Но, тем не менее, ни один сложный и большой проект не способен завершиться успешно без менеджмента. Как бы вы лично к менеджменту не относились, это так. Ну и когда вы сами станете менеджерами и начнете нести ответственность за результат, тогда лучше поймете, делает ли менеджер что-нибудь или нет;
  • "Любой менеджмент должен быть заменен тулзами". Речь про то, что различного рода программы и программые системы, завязанные на правильные методологии, способны устранить промежуточное звено в виде менеджмента. Что не так. Если отбросить категорию "менеджеров", которые занимаются только расстановкой точек в MS Project-е и сбором отчетов о ежедневной загруженности, или же являются всего лишь точкой коммуникаций между руководством и исполнителями, то менеджмент -- он же про работу с людьми. Создание условий для людей, учет их мнений и пожеланий, обучение, решение их проблем, предотвращение конфликтов, устранение последствий конфликтов и т.д. Кто-то всерьез хочет переложить работу с людьми на автоматические тулзы? Ну вперед, чё :)

А вообще, есть замечательная книга Игоря Ашманова "Жизнь внутри пузыря". Там есть целая глава про магов. Так вот, когда я слушаю рассказы Бугаенко про ООП или про то, куда должна двигаться методология разработки программных проектов, я вспоминаю этих самых магов из книжки Ашманова. Чего и вам желаю ;)

четверг, 25 мая 2017 г.

[prog] Интересный момент при проектировании round-robin mbox-а.

Работаю над такой штукой для SObjectizer-а как round-robin mbox. Т.е. почтовый ящик, на который могут подписаться N агентов, но доставка сообщений к ним будет осуществляться по очереди, т.е. сперва первому агенту, затем второму, затем третьему и т.д. Эта штука должна быть удобной, например, при реализации балансировки нагрузки, когда требующие обработки сообщения отсылаются в один и тот же mbox, а распределяться они будут при этом на N агентов-воркеров, прозрачным для отправителя образом.

Подобные вещи и раньше можно было делать, но вручную. А теперь есть возможность предоставить round-robin mbox прямо "из коробки".

Однако, в процессе продумывания реализации round-robin mbox-а обнаружилась неожиданная засада. Дело в том, что в mbox-ах есть такая штука, как delivery filters, т.е. фильтры, которые определяют, имеет ли смысл доставлять конкретное сообщение до конкретного получателя.

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

Чем же мешают фильтры доставки в round-robin mbox-е?

Как в принципе должен работать round-robin mbox? У него должен быть список подписчиков на каждый тип сообщения. В этом списке должен быть явно отмечен текущий элемент -- тот подписчик, которому должно быть доставлено следующее сообщение. Когда сообщение приходит, оно отсылается этому подписчику, после чего текущим элементом становится следующий подписчик (ну или первый, если мы дошли до конца). Все просто.

Но это мы пока не рассматривали фильтры доставки. В случае с фильтрами доставки мы должны для текущего элемента спросить у его фильтра "А можно ли доставлять сообщение этому подписчику?" Если можно, то все хорошо, работает привычная схема. А вот если фильтр говорит "Нет"? Что делать тогда?

Вырисовываются следующие варианты:

  1. Просто выбросить этот экземпляр сообщения. Т.е. текущему агенту в списке сообщение не доставляется (что естественно, т.к. фильтр запрещает доставку) и не делается попытка доставить сообщение следующему агенту в списке. Текущим становится следующий агент в списке (или первый, если достигли конца списка).
  2. Попытаться выбрать другого получателя. Т.е. сразу перейти к следующему агенту и спросить его фильтр доставки. Потом к следующему и т.д. до тех пор, пока получатель не будет найден. Может быть вообще ничего не найдем, но тогда данный экземпляр сообщения просто выбрасывается.
  3. Тупой запрет на использование фильтров доставки в случае round-robin mbox-а. Тогда проблемы нет в принципе.
  4. Update. Объединить все фильтры доставки в один комбо-фильтр. Когда появляется сообщение, оно сперва пропускается через этот комбо-фильтр (т.е. через все фильтры). И только если комбо-фильтр пропускает сообщение, только тогда оно доставляется текущему получателю.

Лично я пока склоняюсь к первому варианту. Логика такая: round-robin предполагает, что пытаемся доставлять по очереди. Сейчас очередь у агента X. Если X отказывается принимать сообщение, то он все равно свою очередь использовал и для следующего сообщения очередь перейдет к другому получателю.

Вот только не уверен, что это не будет сбивать пользователей с толку. Кто что думает?

После небольшого обсуждения и дополнительного обдумывания появился вариант №4, который сейчас и кажется наиболее уместным: сообщение должно удовлетворять всех получателей и только тогда можно выбрать очередного получателя для сообщения.

Кстати, попутно еще один вопрос: а кроме round-robin еще какие-нибудь политики доставки для N агентов кому-нибудь нужны/интересны?

понедельник, 22 мая 2017 г.

[prog.flame] Егор Бугаенко в DevZen подкасте

Есть в Рунете такой подкаст: DevZen. Я его практически никогда не слушаю. За исключением некоторых отдельных случаев: один раз там обсуждали именно что мой пост в моем блоге, один раз там говорили про модный и молодежный взгляд на ООП вообще и ООП в C++ в частности, один раз обсуждали акторов в C++, один раз послушал фрагмент DevZen с участием Григория Демченко и пара выпусков про Лондон и стартапы. Хотя ссылки, которые там накидывают в комментариях стараюсь просматривать, бо временами встречается интересное.

Не слушаю подкат по нескольким простым причинам. Во-первых, сам формат подкастов мне не нравится, прочитать текст для меня гораздо удобнее, чем слушать двухчасовые разговоры (в дороге на работу я провожу мало времени, так что время на прослушивание нужно выкраивать из других активностей). Во-вторых, темы DevZen поднимает такие, которые меня самого мало волнуют и мало касаются. В-третьих, очевидно существует некий возрастной разрыв: то, как ведут себя ведущие подкаста, способы обсуждения и способы общения мной уже воспринимаются как типично молодежные. Может быть, будь мне лет на 15 поменьше, меня бы все устраивало. Но сейчас хочется чего-то более степенного, размеренного, вдумчивого, без навязчивых и настойчивых попыток донести свою точку зрения. Но, повторюсь, это лично мои стариковские заморочки.

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

пятница, 19 мая 2017 г.

[business] Где можно посмотреть примеры текстов коммерческих лицензий на ПО?

Обращаюсь за помощью к своим читателям. Мы думаем некоторые свои разработки распространять под двойной лицензией, т.е. GNU GPL или GNU Affero GPL для использования в OpenSource-проектах + коммерческая лицензия для использования в закрытых проектах. Как раз сейчас работаем над текстом этой самой коммерческой лицензии.

У нас есть несколько текстов коммерческих лицензий от производителей ПО, которые сами продают свое ПО под двойной лицензией. Но это слишком маленькая выборка. Хотелось бы больше.

Посему просьба к читателям блога, у которых случайно завалялся текст какой-нибудь коммерческой лицензии к какому-нибудь OpenSource-софту: могли бы вы поделиться текстом (вычеркнув оттуда всю конфиденциальную информацию, естественно)? Или ссылочкой на подобные тексты в Интернете?

Может быть кто-то может подсказать координаты юристов или юридических компаний в РБ, у которых есть опыт подготовки такого рода лицензий? Именно в РБ.

Связаться со мной можно по мылу eao197 на stiffstream тчк com или eao197 на gmail com.

четверг, 18 мая 2017 г.

[prog] Почему-то сильно не хочется делать CMake основным build-tool-ом

Под влиянием вот этого доклада с C++ CoreHard Spring 2017 решил попробовать еще раз посмотреть в сторону CMake как основного своего build-tool-а. Сам CMake, как по мне, говном был, говном и остался. Но, поскольку люди всерьез интересуются такими построенными поверх CMake вещами, как Conan.io и Hunter, то может пришло время зажать нос и научиться обмазываться CMake-ом?

В чем у меня специфика? В том, что под Windows у меня сейчас, например, десять(!) вполне себе актуальных версий GCC под x64: 4.8, 4.9, 5.1, 5.2, 5.3, 5.4, 6.1, 6.2, 6.3 и 7.1. Плюс к тому три версии Visual Studio (каждая из которых как в x86, так и в x64). Плюс две версии clang (3.9 и 4.0).

Под каждую версию компилятора у меня есть свой bat-файл, в котором настраиваются все пути и все окружение. И для каждого батничка свой ярлык на рабочем столе. Нужен мне, скажем, gcc-4.8, я кликаю на ярлык, попадаю в нужную среду, захожу в нужный мне каталог, запускаю ruby build.rb или ruby some/project/prj.rb. И все.

среда, 17 мая 2017 г.

[prog.thoughts] По мотивам одного из докладов с C++ CoreHard Spring 2017

На прошедшей на днях конференции C++ CoreHard Spring C++ был один весьма неоднозначный доклад. Это доклад Василия Вяжевича "Модульность и управляемая многопоточность встраиваемых С++ приложений — трудности, проблемы, решения". Доклад, пожалуй, самый слабый из всех докладов этой конференции. Тем не менее, если тема многопоточности в C++ интересна всерьез, то с докладом ознакомиться имеет смысл (если смотреть на youtube, то имеет смысл увеличить скорость до 1.25 или даже до 1.5, иначе слушать будет совсем грустно).

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

С одной стороны, докладчик безусловно прав в том, что многопоточное программирование -- это сложно. Одним из следствий этой сложности является как раз сложность отладки, о которой в докладе и говорил Василий. Так что работа с многопоточностью -- это минное поле и нужно быть к этому готовым.

С другой стороны, нужно сказать две вещи, которые, предполагаю, пойдут в разрез с тем, что прозвучало в докладе.

Во-первых, многопоточность выбирается для реализации приложения не просто так. По крайнем мере, если мы говорим об опытных разработчиках, которые понимают, что делают, а не хватаются за std::thread просто потому, что только что прочитали об этом в документации. Как я уже неоднократно говорил, многопоточность используется либо для нужд parallel computing, либо для нужд concurrent computing. И в обоих случаях мы получаем сильно разную клиническую картину:

  • в случае parallel computing количество рабочих потоков у нас будет ограничиваться количеством вычислительных ядер. При этом мы заинтересованы в том, чтобы какой-либо обмен данными между рабочими потоками был сведен к самому минимуму. В идеале, рабочие потоки должно работать над совершенно независимыми и непересекающимися наборами данных. Поэтому отладка таких многопоточных приложений не так сложна, как это может показаться. Ведь каждая нить представляет из себя, по сути, небольшой самостоятельный однопоточный процесс, который очень мало взаимодействует с внешним миром. Следовательно, нас мало волнуют ситуации, когда параллельный поток убежал куда-то вперед или немного подотстал. Но самое главное другое: если у нас задача сократить общее время расчета (а для этого и нужен parallel computing), то мы можем использовать либо многопоточность, либо многопроцессность. И для одного, и для другого есть свои показания и протовопоказания. Но смысл в том, что для parallel computing в каких-то условиях выбор в пользу многопоточности будет единственно верным. И это не зависит о того, нравится ли нам многопоточность и умеем ли мы отлаживать многопоточный код;
  • в случае concurrent computing количество рабочих потоков ограничивается лишь степенью нашей распущенности :) Параллельные потоки в concurrent computing мы используем либо для того, чтобы снизить степень влияния одной независимой задачи на другую независимую задачу (например, запись в файл не должна блокировать запрос к БД), либо для того, чтобы упростить реализацию какой-то независимой задачи. Так, какую-то последовательность действий нам может быть проще записать в виде простой последовательности синхронных вызовов, чем делать то же самое посредством конечного-автомата с размазыванием логики между отдельными callback-ами. Проблем с многопоточностью в случае concurrent computing гораздо больше, поскольку:
    • нашим задачам, как правило, придется оперировать над какими-то общими разделяемыми данными. Соответственно, если это мутабельные данные, то у нас начинается головная боль по защите разделяемых мутабельных данных и по обеспечению их консистентности;
    • поскольку часть наших задач будет так или иначе зависеть друг от друга и взаимодействовать друг с другом, то нам важна будет синхронизация по времени в каких-то узловых точках. Т.е. если мы делаем задачу A, а параллельно выполняется задача B, результат которой когда-то потребуется в задаче A, то для нас может быть важно, чтобы задача B не затормозила и была выполнена до того момента, когда внутри A мы обратимся к результатам B.
    И вот все это в совокупности и приводит к тому, что отладка многопоточных приложений превращается в сплошной геморрой. Ведь нам приходится иметь дело и с разделяемыми мутабельными данными, которые могут поменяться в любой момент извне. И с "времянкой", когда параллельно выполняющиеся потоки либо сильно притормаживают, либо уходят далеко вперед.

Так вот проблема доклада Василия Вяжевича в том, что он не обозначил явным образом то, что речь будет идти только о специфике задач concurrent computing. И что представляемое слушателям решение возможно потому, что у задач из категории concurrent computing есть интересное свойство: зачастую им вообще не нужен параллелизм, можно обойтись квазипараллелизмом. Как раз то, что было в ранних версиях Windows 3.*, работавших в реальном режиме процессора.

Однако, для того, чтобы обеспечить работу множества задач на одной единственной рабочей нити, нам нужно сделать выбор между:

  • использованием какого-то из вариантов объекта с коллбэками. Т.е. есть объект, у которого некий фреймворк дергает тот или иной коллбэк. И работа фреймворка не может продолжиться, пока объект не вернет управление назад. По этому принципу работают самые распространенные акторные фрейворки для C++ (QP/C++, CAF, SObjectizer) и не только для C++ (например, Akka);
  • использование сопрограмм, которые фреймворк может приостанавливать и возобновлять. Например, когда из сопрограммы дергается какой-то вызов самого фреймворка и фреймворк получает возможность заморозить текущую сопрограмму и разморозить какую-то другую сопрограмму. По этому принципу работают, например, Boost.Fiber и Synca для C++.

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

Во-вторых, то, что показывал Василий Вяжевич в своем докладе, на мой взгляд, является отличной иллюстрацией того, о чем я говорил в конце своего доклада "Шишки, набитые за 15 лет использования акторов в C++":

...реализовать в своем фреймворке какую-то идею и показать ее работоспособность — это не так уж и сложно. Можно потратить несколько месяцев труда и получить вполне себе работающий и интересный инструмент. Это все делается на чистом энтузиазме. Буквально: понравилась идея, захотел и сделал.
А вот оснащение того, что получилось, всякими вспомогательными средствами, вроде сбора статистики или трассировки сообщений — это уже скучная рутина, на которую не так то и просто найти время и желание.

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

У вас есть проблема. Вы думаете над ее решением и вам в голову приходит отличная мысль:
-- Да тут же можно использовать регулярные выражения!
Все. Теперь у вас есть две проблемы.

Вот так и с самодельными фреймворками для диспетчеризации задач. Вначале они решают ваши проблемы. Потом сами становятся вашими проблемами. Так что если вы сталкиваетесь с ситуацией, когда для concurrent computing вам нужно множество объектов-тасков с коллбэками, а так же какой-то диспетчер для них, посмотрите сперва по сторонам. Возможно, инструменты вроде QP/C++, CAF, SObjectizer или даже Intel TBB уже содержат то, что вам нужно. Уверяю, посмотреть по сторонам будет быстрее и дешевле, чем налабать на коленке что-то за пару дней, а потом саппортить это на протяжении нескольких лет, а то и дольше.

Кроме того, хоть я и сам без пиетета отношусь к формальному делению на какие-то модели, вроде Actor Model, CSP или что-то еще, но. Не могу не отметить, что когда признаки той или иной модели легко проявляются в некоем фреймворке, то гораздо проще понять, на что способен фреймворк и как этот фреймворк использовать. Так, если мне говорят про Actor Model, то это одни подходы к использованию. Если про CSP-шные каналы, то другие.

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


В общем, в сухом остатке: не нужно велосипедить, есть те, кто этим занимается давно и с гораздо большим удовольствием. Предоставьте другим весело бегать по граблям многопоточности :)