понедельник, 9 ноября 2020 г.

[life.sport] Маленькое послесловие к завершившимся велосипедным гранд-турам

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

В плане накала борьбы и непредсказуемости результатов гранд-туры 2020-го оказались чем-то феноменальным. Уж не знаю, как скоро мы сможем увидеть что-либо подобное еще раз.

На Тур де Франс и Джире победители общего зачета определились лишь в последний(!) соревновательный день. И на Вуэльте в последний соревновательный день идущий на второй позиции Карапас таки успешно атаковал Роглича и сумел финишировать на этапе на 20 секунд раньше своего соперника, но этого не хватило. Разрыв между первым и вторым местом на Вуэльте в результате составил всего 24 секунды. Всего 24 секунды после трех недель гонок! Кстати, разрыв на Туре ~50 секунд, на Джире ~40 секунд. Во всех трех гонках между первым и вторым местом меньше минуты.

В общем, феноменальный год.

Теперь бы дождаться следующего...

Пожелаю всем спортсменам, болельщикам, а так же читателям мого блога здоровья. Берегите себя!

четверг, 5 ноября 2020 г.

[books.management] Прочитал давеча книжицу от Додо Пицца про Додо Пиццу

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

Сначала она где-то валялась без дела, а вот давеча попалась на глаза и, в условиях добровольной самоизоляции, я ее таки прочитал. Благо времени на это много не потребуется, ибо текста там не так уж много, а объема добавляют картинки и специфическое оформление.

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

Чего лично мне очень не хватило в "Додо книга", так это пусть даже краткого, но жизнеописания основателя "Додо Пиццы", Федора Овчинникова. Имхо, было бы интересно узнать, какой опыт помог ему основать такое не маленькое и непростое дело.

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

понедельник, 2 ноября 2020 г.

[work] Маэстро художественного слова в ИТ

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

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

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

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

Именно из-за этого самого тумана упомянутые выше мастера изящной словесности в принципе не могут изъясняться лаконично и выражать свои мысли четко и точно у них не получается от слова совсем. Поэтому все, что они извергают наружу оказывается тем самым нескончаемым потоком сознания.

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

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

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

пятница, 30 октября 2020 г.

[life.business] Несколько слов о "спиральной динамике" вообще и о графомании ее апологета Максима Цепкова в частности

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

Источник изображения здесь

Клер Грейвз, его теория, спиральная динамика поверх теории Грейвза

вторник, 27 октября 2020 г.

[work] Наткнулся тут на невероятное...

В поисках информации о "спиральной динамике" нашел такого автора на vc.ru: Максим Цепков. А среди его статей ознакомился вот с этой: "Реальность цифрового мира: проекты делает некомпетентная команда". И вот в этой статье практически сходу споткнулся о пару-тройку моментов, которые заставили всерьез задуматься о том, а не сказочный ли пишет все эти буквы? Уж простите мне мой французский, но запись в блог сразу после прочтения, еще под свежими впечатлениями.

Итак, цитата:

Получается, что нам нужно делать проекты некомпетентной командой. В то время в любом учебнике по менеджменту написано: обязательным условием для успеха проекта является компетентная команда, поэтому определите, какие компетентные специалисты вам нужны, найдите их и привлеките к проекту. Это оказывается невозможным. Как можно ли в таких условиях успешно делать проекты?

Оказывается, для этого уже давно есть методы. Первые из них появились, естественно, в IT как раз тогда, когда было осознанно, что регламенты и правила не работают, а ключевым фактором успеха является человеческий фактор. Об этом есть классическая книга Тома ДеМарко «Peopleware» (1987), которая в русском переводе так и называется «Человеческий фактор».

И как ответ на эту ситуацию появился Agile. Он взлетел именно поэтому, что появился во время прихода персоналок. Персоналки ведь пришли не домой, они сделали компьютеры доступными для мелких и средних компаний. И потребовалось массово автоматизировать бизнес, возник дефицит разработчиков. Их не было, выпуск институтов не увеличился. И именно Scrum и Agile обеспечили решение этой проблемы, позволив успешно делать проекты некомпетентной командой. Это был один из ключевых факторов их успеха и широкого распространения. В России, кстати, мы это не очень ощутили, потому что именно тогда, в период появления персоналок, развалилась оборонка и много квалифицированных инженеров ушли в айтишники, они демпфировали этот кризис.

Что меня здесь смущает?

Первое. Agile и персоналки. Если я правильно помню, то первопроходцы Agile делали приснопамятную систему расчета компенсаций для Крайслера в 1993-1999 годах как раз таки не для персоналок вообще, а для мейнфреймов. Могу ошибаться, поэтому если кто-то владеет информацией лучше меня, то поправте плиз.

Далее, период развития интереса к Agile, начиная с появления Agile Manifesto -- это уже нулевые годы. Когда у персоналок был не то, чтобы приход. Они уже давно пришли. А приход тогда как раз был у Web-а. И именно в конце 1990-х и начале нулевых стартовал и нарастал массовый переход от десктопа к Web-у. В условиях когда не было ни толком развитых Web-технологий, ни опытных Web-разработчиков, зато спрос на Web-разработку был сумасшедший. Так если уж благодаря чему-то Agile и взлетел, так это благодаря Web-разработке.

Второе. Что-то мне трудно припомнить, чтобы в 1990-е в России после распада оборонки квалифицированные инженеры массово уходили в айтишники. При том, что как раз в оборонке до 1990-х огромное количество разработчиков и трудилось. А потом осталось без куска хлеба. В прямом смысле. И поэтому уже существующие профессиональные кадры разбегались и выживали кто как может: кто-то уехал, кто-то переквалифицировался на бух- и складской учет (dBase/FoxBase/Clarion, а затем и 1C с Галактикой и Ко), кто-то ушел в преподавание, кто-то смог уйти в сисадмины (в банках в то время был большой спрос), кто-то тупо торговал широпотребом на рынке.

Так что как-то с моими воспоминаниями ну никак не бьется. Но я и не из России. Поэтому опять же, вопрос к более знающим людям: действительно ли в 1990-х квалифицированные инженеры из оборонки в РФ уходили в айтишники?

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

понедельник, 26 октября 2020 г.

[prog.c++] Особенность aggregate initialization в современном C++, о которой я и не подозревал

Некоторое время назад попробовал разобраться с тем, как работает трюк, описанный в статье "Reflection in C++14". И очень долго тупил и не понимал, как же так получается, что попытки увеличивать количество параметров в выражении aggregate initialization ведут к должному результату... Т.е. сперва делается T{a1}, затем T{a1, a2}, затем T{a1, a2, a3} и т.д. И останавливается это все на aN, где N и есть количество полей в структуре T.

А тупил и не понимал потому, что считал, что в выражении aggregate initialization нужно передавать начальные значения для всех полей структуры T. Т.е., если в T четыре поля, то и в aggregate initialization нужно отдать именно четыре значения. Не больше, не меньше. А именно четыре.

Ну и вот оказалось, что в главном-то я и не прав. В aggregate initialization можно отдать и меньше значений. Вот для иллюстрации работающий пример (убедиться можно на wandbox):

#include <iostream>

struct Demo {
    int a_;
    int b_;
    int c_;
    int d_;
};

std::ostream & operator<<(std::ostream & to, const Demo & d) {
    return (to << '(' << d.a_ << ',' << d.b_ << ',' << d.c_ << ',' << d.d_ << ')');
}

int main() {
    {
        Demo d{};
        std::cout << "First: " << d << std::endl;
    }
    {
        Demo d{1, 0};
        std::cout << "Second: " << d << std::endl;
    }
    {
        Demo d{1, 0, 42, 15};
        std::cout << "Third: " << d << std::endl;
    }
}

Вот уж, что называется, век живи, век учись, а помрешь все равно дураком ;)

среда, 21 октября 2020 г.

[prog.c++] json_dto-0.2.11 released

json_dto is a thin wrapper around RapidJSON library we wrote several years ago. It's surprising for us that this small bicycle is used by someone outside our team. Sometimes users show us use-cases we just weren't thinking about. And we add new features to json_dto to fulfill expectations.

The last updates to json_dto add a possibility to customize formatting of (de)serialized values by specifying custom Reader_Writers. For example let's imagine that we have a struct with a `std::map<std::uint32_t, int>` field:

struct example_data {
   std::map<std::uint32_t, int> m_weights;
   ...
};

It's impossible to write a simple (de)serialization code for example_data in the form:

struct example_data {
   std::map<std::uint32_t, int> m_weights;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory("weights", m_weights)
         ...
         ;
   }
};

because RapidJSON expects string values as keys, but json_dto (de)serializes `std::uint32_t` as integers. And the naive implementation of `json_io` shown above leads to run-time error during serialization.

Now json_dto allows to use custom formatters for fields to be (de)serialized:

struct simple_reader_writer {
   // Those methods will be used for (de)serializing of map's keys.
   void read(
      json_dto::mutable_map_key_t<std::uint32_t> & key,
      const rapidjson::Value & from) {
      ... // Deserializing key from a string.
   }
   void write(
      const json_dto::mutable_map_key_t<std::uint32_t> & key,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      ... // Serializing key as a string.
   }

   // Those methods will be used for (de)serializing of map's values.
   void read(
      int & v,
      const rapidjson::Value & from) {
      json_dto::read_json_value(v, from); // Just reuse json_dto.
   }
   void write(
      const int & v,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      json_dto::write_json_value(v, to, allocator); // Just reuse json_dto.
   }
};

struct example_data {
   std::map<std::uint32_t, int> m_weights;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory(
              // Explicit specification of custom Reader_Writer for that field.
              // The usage of apply_to_content_t tells that custom formatter
              // should be applied to every item of the container.
              json_dto::apply_to_content_t<simple_reader_writer>{},
              "weights", m_weights)
         ...
         ;
   }
};

So now keys of `example_data::m_weights` will be (de)serialized as strings.

But custom Reader_Writers allow to go further. Let's imaging that `example_data` contains yet another `std::map<uint32_t, int>`:

struct example_data {
   std::map<std::uint32_t, int> m_weights;
   std::map<std::uint32_t, int> m_colors;
   ...
};

where keys of `example_data::m_colors` should be represented in the form `#xxxxxx`, where `xxxxxx` is hexadecimal representation.

We can create another custom Reader_Writer:

struct color_hex_reader_writer {
   // Those methods will be used for (de)serializing of map's keys.
   void read(
      json_dto::mutable_map_key_t<std::uint32_t> & key,
      const rapidjson::Value & from) {
      ... // Deserializing key from a string.
   }
   void write(
      const json_dto::mutable_map_key_t<std::uint32_t> & key,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      ... // Serializing key as a string.
   }

   // Those methods will be used for (de)serializing of map's values.
   void read(
      int & v,
      const rapidjson::Value & from) {
      json_dto::read_json_value(v, from); // Just reuse json_dto.
   }
   void write(
      const int & v,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      json_dto::write_json_value(v, to, allocator); // Just reuse json_dto.
   }
};

and use it for (de)serialization of `example_data::m_colors`:

struct example_data {
   std::map<std::uint32_t, int> m_weights;
   std::map<std::uint32_t, int> m_colors;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory(
              json_dto::apply_to_content_t<simple_reader_writer>{},
              "weights", m_weights)
         & json_dto::mandatory(
              json_dto::apply_to_content_t<color_hex_reader_writer>{},
              "colors", m_colors)
         ...
         ;
   }
};

The full working example can be seen here.

PS. I don't like to answer questions like "Is json_dto better than nlohmann::json, cereal or any other similar library?" We started to use RapidJSON several years ago and we didn't know about many of the JSON-libraries well known today. At some time we decided to simplify our marriage with RapidJSON and wrote json_dto. Since then it's easier for us to continue to use json_dto than to switch to any other library. So if you are happy with nlohmann::json there is no need to see for something else. But if you have to stay out of nlohmann::json for any reason there is json_dto ;)

PPS. We love reinventing bikes and we know how to do it: RESTinio and SObjectizer are also out of our garage.