среда, 16 октября 2019 г.

[prog.c++] Наткнулся на неожиданную для себя особенность объявления static constexpr в классе

Столкнулся вчера с ситуацией, в которой не компилировался код, казавшийся мне нормальным. Вот минимальный воспроизводимый пример:

#include <cstdint>

class vholder_t
{
public :
   using underlying_type_t = std::uint_least16_t;

   class trusted
   {
      const underlying_type_t m_value;

   public:
      explicit constexpr
      trusted( underlying_type_t v ) noexcept : m_value{v} {}

      constexpr auto
      get() const noexcept { return m_value; };
   };

   static constexpr trusted max{1000u};

private :
   underlying_type_t m_value;

public :
   vholder_t( trusted v ) noexcept : m_value{ v.get() }
   {}
};

int main()
{
   using trusted = vholder_t::trusted;

   constexpr trusted max{1000u};

   vholder_t v{ trusted{200u} };

   return 0;
}

Ошибка возникала в строчке:

static constexpr trusted max{1000u};

Диагностика у разных компиляторов была разной, в основном все говорили о невозможности использовать trusted в constexpr контексте. Кто-то ругался на неопределенные конструкторы в trusted, кто-то на то, что max должен инициализироваться константой.

Собственно, на эту красоту можно полюбоваться на godbolt-е: https://gcc.godbolt.org/z/lP0XlT.

Самой полезной оказалась диагностика от GCC-8 (и GCC-9). Оказалось, что компилятор почему-то считает, что в месте объявления max тип trusted еще не определен, поэтому trusted и не может быть задействован в constexpr контексте.

Поэтому был применен следующий workaround:

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

[prog.c++] Упоролся шаблонами по полной программе или результат третьего подхода к удобному парсеру HTTP-полей в RESTinio

История неудачных попыток создать удобный парсер HTTP-полей для RESTinio продолжается. Результат третьей попытки под катом. Рассказ о первой попытке здесь, а о второй -- здесь.

Анализируя результат второй попытки появилась, как тогда казалось, стройная идея по разделению парсера на такие понятия, как value_producer, value_transformer и value_consumer. По первым прикидкам казалось, что это позволит делать декларативное описание структуры значения HTTP-поля на основании грамматики этого поля из RFC.

Оно-то как-то так и оказалось. Но уж слишком многословно и мудрено.

В качестве примера под катом находится класс для разбора значения HTTP-поля Cache-Control. Содержимое этого поля в RFC определяется как:

Cache-Control   = 1#cache-directive

cache-directive = token [ "=" ( token / quoted-string ) ]

При этом конструкция вида 1#element определяется вот так:

1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )

Т.е. правило для Cache-Control можно развернуть так:

Cache-Control   = *( "," OWS ) cache-directive *( OWS "," [ OWS cache-directive ] )

cache-directive = token [ "=" ( token / quoted-string ) ]

Т.е. этому правилу может удовлетворять, например, такая последовательность:

, ,   , max-age=5, , , no-transform,  ,,, ,

Итак, вот что получилось:

суббота, 12 октября 2019 г.

[work;life] СтифСтриму три года. Наполовину реклама, наполовину рефлексия на эту тему

Намедни нашей небольшой компании исполнилось три года. Поэтому поводу тост^W пост.

Было очень непросто. Временами возникали сомнения в том, а выживем ли вообще. Непросто и сейчас. В обозримом будущем просто тоже не будет. Но не зря мы себя назвали "Упрямый поток", упертости в желании двигаться вперед нам не занимать. Так что мы все еще здесь.

Кому и что мы можем предложить

Постепенно мы сосредоточились на двух вещах:

  • во-первых, наши собственные открытые продукты и связанные с ними сервисные услуги. Так что если кому-то нужна поддержка или консультация по SObjectizer и/или RESTinio, или доработка наших продуктов под ваши специфические нужды, то смело обращайтесь. Без помощи не оставим;
  • во-вторых, работа с небольшими клиентами/заказчиками, которые остались один на один с каким-то (не очень) старым софтом, без которого не обойтись, но который некому фиксить/сопровождать/развивать. На рынке не так уже много спецов по C++, маленькие компании не всегда могут себе позволить держать такого в штате или обратиться к крупному аутсорсеру. В таких случаях обращаются к нам и мы разбираемся в чужом говнокоде, заставляем это "наследие" работать. Высказываем свои соображения, в том числе и по целесообразности продолжения "жрать кактус".

Мы хоть и специализируемся на C++ и, по мере надобности, приводим в рабочее состояние копролиты на чистом С, но не имеем цели всеми средствами удержать клиента в рамках C/C++. Если проблему клиента выгоднее решить на Go, C# или Java, мы именно это и порекомендуем сделать. Лучше пусть клиент возьмет других исполнителей, нежели со временем обнаружит что мы его, мягко говоря, накололи.

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

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

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

Любой желающий может заглянуть в потроха наших разработок (SObjectizer и so5extra, RESTinio, json_dto). Если вас такое качество устраивает, то обращайтесь, пообщаемся.

Рекордов по срокам не ставим и жопу на британский флаг не рвем. Тут уж извините, быстро только кошки родятся, а наспех написать надежно работающий код на C++ (и тем более на C) нельзя. Если вы знаете кого-то, кто умеет, то вам повезло, держитесь за этого исполнителя обеими руками. Однако, что такое "нужно было вчера" понимаем. Например, если сбоит то, что должно работать в режиме 24x7, то стараемся войти в положение.

Наш стандартный рейт для краткосрочных заказов 35USD в час. Основная часть клиентов у нас пока из exUSSR и мы понимаем, что этот ценник для многих слишком высокий, но дешевле не можем, извините. Более низкую стоимость мы выставляем для долгосрочных работ или если дело касается открытых доработок наших OpenSource решений.

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

Стоило ли оно того и некоторые выводы/соображения?

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

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

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

Можно выделить несколько вещей о которых я, в принципе, знал, но объем и значимость которых не осознавал в полной мере:

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

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

Ваши проблемы будут с вами 24x7x365. Если не понятно почему, то см. выше про "Никто кроме вас".

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

Воронка продаж. Она существует.

Время -- деньги или "time to market really matters". Ваше отношение ко времени и деньгам изменится. Одним из основных вопросов станет "когда продукт станет доступен на рынке?", а каждый день просрочки вы в прямом смысле начнете ощущать собственным кошельком. Соответственно, качество вашего продукта станет всего лишь одним из свойств продукта. Именно поэтому выше я и говорил, что мы работаем "более-менее качественно": качество стоит очень дорого, мало кто готов за это платить, т.к. платить приходится не только и не столько деньгами, сколько временем, которое не купить и которым никто не располагает в достаточной мере. Ну кроме наемных работников, само собой ;)

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

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

Ничто не вернет времени, которое вы потратили на бизнес, а не на семью. Ничто.

Ну с большего как-то все. Надеюсь, что никого сильно не напугал ;)

Благодарности

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

Приносим извинения тем, с кем не смогли поработать в силу своей загруженности и каких-то других обстоятельств. Разорваться не можем, увы. Да и shit happens, ничего не поделать.

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

Найти нас можно здесь: stiffstream.com.

среда, 9 октября 2019 г.

[prog.c++] Первые результаты второго подхода к удобному парсеру HTTP-полей в RESTinio

Продолжение истории, начатой некоторое время назад. Первая попытка сделать некий удобный в использовании набор инструментов для парсинга HTTP-полей в RESTinio завершилась результатом, который вызывал противоречивые ощущения и меня лично не удовлетворил. В том числе и потому, что сложные HTTP-поля, вроде поля Accept, парсить было бы совсем не просто.

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

[prog.c++] Что-то я неслабо затупил из-за отсутствия fold expression в C++14

Столкнулся со следующей задачей: есть экземпляр std::tuple, который содержит объекты-парсеры. Нужно пробежаться от первого элемента тупла к последнему и для каждого парсера вызвать метод try_parse с определенными параметрами. Но! Нужно прервать эту итерацию как только очередной try_parse вернет false.

В C++17 это элементарно записывается посредством fold expression:

templatetypename Tuple, std::size_t... Indexes >
bool try_parse_impl(
   const std::string & source,
   Tuple & t, 
   std::index_sequence<Indexes...>)
{
   return (... && std::get<Indexes>(t).try_parse(source));
}

templatetypename... F >
bool try_parse(const std::string & source, std::tuple<F...> & parsers)
{
   return try_parse_impl(source, parsers, std::index_sequence_for<F...>());
}

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

А вот как сделать тоже самое, но в C++14, где fold expression нет?

Единственное, что у меня пока вышло -- это вот такое:

templatebool valid_index, std::size_t I >
struct try_parse_impl
{
   templatetypename... Parsers >
   static bool apply(const std::string & source, std::tuple<Parsers...> & t)
   {
      if( std::get<I>(t).try_parse(source) )
         return try_parse_impl< (I+1 < sizeof...(Parsers)), I+1 >::apply(source, t);
      else
         return false;
   }
};

template< std::size_t I >
struct try_parse_impl< false, I >
{
   templatetypename... Parsers >
   static bool apply(const std::string &, std::tuple<Parsers...> &)
   {
      return true;
   }
};

templatetypename... F >
bool try_parse(const std::string & source, std::tuple<F...> & parsers)
{
   return try_parse_impl< (0 < sizeof...(F)), 0 >::apply(source, parsers);
}

Возможно, вместо всего этого как-то можно было бы обойтись более прямой работой с std::index_sequence. Но что-то для этого моего понимания механизма распаковки параметров в variadic templates не хватает. И примеры, которые я находил в Интернетах не очень помогают, т.к. там идет итерация по всем элементам тупла, без анализа результата на очередной итерации и прерывания цикла.

Поиграться с полным примером можно здесь.

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

пятница, 4 октября 2019 г.

[life.work] Юбилей, наверное. 25 лет профессиональной деятельности как-никак

По случаю тяпницы позволю себе немного погрузиться в воспоминания. Если мне не изменяет склероз, то где-то в октябре 1994-го года я устроился инженером-программистом в КБ Системного Программирования, где для меня и была заведена трудовая книжка. Так что 25 лет назад началась моя профессиональная деятельность в области разработки программного обеспечения.

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

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

Ну в общем, как-то так. Почему-то показалось, что 25 лет -- это срок о котором можно написать пару срок.

Представить себе еще 25 лет в профессии, почему-то страшно :(

Уверен, что если не произойдет какого-то глобального катаклизма, вроде войны между крупными государствами, то профессия программиста будет все еще востребована. Не удивлюсь, что и на C++ разработчиков через 25 лет будет спрос...

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

Вот что я о себе написал в начале 2000-х и, полагаю, это было весьма точное определение:

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

С такими симптомами в анамнезе будет неудивительно, если и через 25 лет я буду строить какие-то велосипеды и создавать с нуля работающие системы. В общем, поживем -- увидим. 25 лет, как оказалось, не срок :)

суббота, 28 сентября 2019 г.

[comp.prog.thoughts] Праздное про ноутбуки и производительность софта

Позволю себе еще раз продолжить тему ноутбуков, ибо давеча был несколько удивлен. Дело в том, что когда у меня летом обострились проблемы с моими старыми рабочими ноутами и начались поиски новой рабочей машинки, я разыскал у себя древний Lenovo ThinkPad E130. Что-то типа вот этого, с двухядерным Pentium, работающем на частоте 1.4MHz, с 4GiB RAM и 320Gb HDD.

Купил я его в начале осени 2012-го года (т.е. ровно 7 лет назад) в качестве рабочей лошадки для менеджера, коим я тогда был. Ноут маленький, не тяжелый, прочный и надежный (я как-то на него чай пролил и ему хоть бы хны, т.к. у него оказалась влагозащищенная клавиатура). Но, самое важное -- он был дешевым и его было не жалко таскать с собой повсюду. Уже не помню, во сколько он мне тогда обошелся, что-то в районе $500 что по тем временам для ноутбука было немного.

[prog.c++] В склерозник: пособия по метапрограммированию на C++11

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

Peter Dimov. Simple C++11 metaprogramming

Peter Dimov. Simple C++11 metaprogramming, part 2

Мне понравилось. Все коротко и по делу. Даже я смог более-менее разобраться, что уже о чем-то да говорит.

пятница, 27 сентября 2019 г.

[prog.c++] Двойственные чувства после достижения задуманного результата

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

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

Итак, потихонечку развитие RESTinio дошло до стадии, когда стало ощущаться отсутствие некоторых полезных вещей. Например, RESTinio позволяет получить доступ к значению HTTP-поля из заголовка (вроде поля "Content-Type"), но зато со значением этого поля уже нужно будет разбираться самостоятельно. Т.е. если вы берете поле "Content-Type", а там лежит "text/plain; charset=utf-8", то парсить эту строку вам нужно будет самим, вручную.

Подумалось, что это не есть хорошо и что RESTinio должно предоставлять что-то пользователю. Но что именно?

В результате было решено не делать в RESTinio полную поддержку полноценного разбора HTTP-полей, а предоставить пару простых функций, которые могут взять содержимое HTTP-поля и разбить его на отдельные значения. Так, из строки "text/plain; charset=utf-8" пользователь может с помощью RESTinio получить отдельные подстроки "text/plain" и "charset=utf-8". А с подстроками уже работать несколько проще.

Но тут возникает вопрос: а как именно должен выглядеть API для такого вот парсинга?

Первый вариант, который мне более-менее понравился и который был достаточно быстро и просто реализован, выглядит так:

вторник, 24 сентября 2019 г.

[prog] Еще один наглядный пример зачем нужен SObjectizer и подобные фреймворки

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

есть таск приготовить пирог, он «верхний». в его реализации есть вызовы тасков: сходи в магазин за ингридиентами пирога, подготовь ингридиенты, испеки. вот эти три явно только последовательно могут быть выполнены.

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

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

теперь верхний таск получив сырой пирог передает его таску выпекателю (конечно, подписавшись на окончание). когда выпекатель закончит, он вызовет верхний таск через калбек.

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

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

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

ИМХО, полезность инструментов вроде SObjectizer, CAF, cpp-taskflow, Boost.Fiber и им подобных в том, что вы можете тупо взять и быстро набросать черновое решение вашей задачи, чтобы посмотреть что в принципе получается. Получается ли вообще. Или вообще не получается. Если более-менее получается, то что у вас с производительностью и другими показателями.

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

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

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

Делать свой велосипед можно только если вы четко, на 146%, убедились в том, что существующие чужие разработки вас совершенно не устраивают. И только если у вас есть ресурсы на это занятие. Причем не только на первоначальную реализацию, но и на последующую поддержку.

Так что, если вы не Yandex, не Kaspersky Lab, не Mail.ru и, уж тем более, не Google/Facebook/Amazon/Aliexpress, то не делайте свои велосипеды. Попробуйте сперва что-нибудь готовое. Благо, есть что попробовать.


Если у вас есть задача, но недостаточно опыта, чтобы понять, как к ней подступиться и что использовать для ее решения, то возьмите SObjectizer спросите у нас ;)

понедельник, 23 сентября 2019 г.

[prog] Наглядный пример роста объема функции при эволюции кода

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

Речь о том, что далеко не всегда объем функций/методов удается держать под жестким контролем. Даже мне, давнему фанату принципа, что код функции должен умещаться на один экран. В качестве примера приведу код функции, над которой как раз таки мне самому довелось поработать. Сначала то, что было изначально. Затем то, что получилось после начала эксплуатации, исправлении одной серьезной проблемы и добавления новых хотелок после накопления некоторого опыта эксплуатации. Код из реального проекта, поэтому все комментарии удалены.

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

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

Итак, вот с чего все начиналось:

суббота, 21 сентября 2019 г.

[prog.history] Между тем COBOL-у исполняется 60 лет и исчезать он никуда не собирается

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

В общем, долголетие COBOL-а заставляет задуматься о том, как долго могут жить языки программирования, получившие в свое время широкое распространение.

Свежая статья на тему COBOL-а: "COBOL turns 60: Why it will outlive us all"

А я нескромно дам ссылочку на аналогичную запись из этого блога, написанную к 50-летию COBOL-а. Там ряд интересных фактов приведен. Ряд из которых, наверное, продолжает оставаться актуальным до сих пор.

пятница, 20 сентября 2019 г.

[prog.facepalm] Никогда такого не было и вот опять: Ошибки аллокации достаточно бесполезно ловить в пользовательской программе.

Ну вот как же задалбывают горе-программисты, которые проповедуют вот такие взгляды:

Ошибки аллокации достаточно бесполезно ловить в пользовательской программе.

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

Во-вторых, как минимум на десктопных Linux по умолчанию включён overcommit, который делает невозможной локальную обработку ошибки выделения памяти.

В-третьих, если вы пишете прикладную программу, близкую к системной в плане управления ресурсами (веб-сервер, сервер БД), то у вас и так весьма особенные нужды в выделении памяти. Часто используются пулы, маппинг файлов/анонимной памяти прямо от системы. Куча в первую очередь интересна "совсем прикладным" программам, которым нехватка ресурсов неинтересна.

Уже столько раз эта тема поднималась, в том числе и мной в этом блоге (пример), что уже нет сил расписывать контраргументы в очередной раз.

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

Так что особого энтузиазма по поводу светлого будущего софтостроения я не питаю :(

пятница, 13 сентября 2019 г.

[prog.memories] Vim, Ruby, Mxx_ru -- пятнадцать лет в пути...

Когда-то давно, в сентябре 2009-го года здесь появилась первая заметка про мое знакомство с ViM, Ruby и появление Mxx_ru: ViM, Ruby, Mxx_ru – пять лет в пути! Часть первая: Mxx_ru (вот вторая часть). Спустя пять лет вышло продолжение истории: Vim, Ruby, Mxx_ru -- десять лет в пути... И вот, спустя еще пять лет, можно написать очередную часть этой истории.


Итак, ViM. Все еще мой основной редактор для написания кода. Пользуюсь им и под Windows, и под Linux, и под FreeBSD. Под Linux-ом, кстати говоря, ViM как-то заметно шустрее работает.

Назвать себя продвинутым пользователем ViM-а не могу, знаю и применяю лишь некий базовый набор команд. Подозреваю, что лет 10 назад я знал про ViM гораздо больше. Но многие знания были утеряны за время менеджерства. Ну и сейчас программирование занимает далеко не 100% моего времени, так что надобности сильно погружаться в дебри ViM-а нет.

Тем не менее, с полной уверенностью могу сказать сейчас про себя: 15 years with Vim and steel learning :) And happy Vimmming!


Раздел второй, Ruby. В последний раз что-то более-менее серьезное писал на Ruby когда в начале 2016-го года добавлял в Mxx_ru поддержку работы с зависимостями (под условным названием MxxRu::externals). С тех пор пишу разве что небольшие одноразовые программки на выброс.

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


Раздел третий, Mxx_ru. Чем больше приходится иметь дел с CMake, тем больше радуюсь, что у меня есть Mxx_ru. Но, боюсь, радоваться мне остается недолго. В C++20 приняли какую-то (пока) неведомую для меня хрень в виде хитровывернутых модулей. Ну оно-то понятно, как можно в C++ добавить что-то понятное, простое и удобное? Очевидно, что никак. Такого не бывает, все должно быть через боль и страдания, это же C++...

Так вот, когда поддержка модулей появится в основных мейнстримовых компиляторах (т.е. VC++, GCC, clang), то придется делать выбор: либо допиливать Mxx_ru до поддержки C++ных модулей, либо полностью уходить с Mxx_ru.

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

Так что если не найдется какая-то гораздо более вменяемая альтернатива CMake (в виде какого-нибудь Meson-а или GN), то вполне возможен сценарий появления на свет Mxx_ru-2.0.


Ну вот как-то так. 15 лет развития какой-то истории -- это совсем немало. Точно могу сказать, что затевая Mxx_ru в августе 2004-го года я вообще не надеялся на то, что этот инструмент проживет столько лет. Теперь уже и самому стало очень интересно, будет ли через пять лет продолжение. И если будет, то какое именно?

Жизнь покажет.

пятница, 6 сентября 2019 г.

[prog.c++] Проверки на noexcept "для бедных"

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

Многие жалуются, что в коде не видно, откуда исключения могут вылететь. ИМХО, это просто из-за недостатка опыта. Если заставить себя думать о том, что исключения могут вылететь откуда угодно, то со временем к этому привыкаешь. И начинаешь понимать, что на самом деле гораздо более важно иметь возможность увидеть, откуда исключение вылететь не может.

В C++11 в этом направлении сделали важный шаг: добавили в язык спецификатор noexcept. Так что теперь из прототипа функции можно узнать о том, что она исключений не бросает.

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

void some_complex_class::cleanup() noexcept {
   cleanup_part_one();
   try {
      cleanup_part_two();
      cleanup_part_three();
   }
   catch(...) {} // Just ignore exceptions.
   cleanup_part_four();
}

Можно легко накосячить.

четверг, 5 сентября 2019 г.

[prog.c++] Небольшое, но важное обновление для SObjectizer-а.

Мы обновили SObjectizer до версии 5.6.1. Изменений совсем мало, просто дошли руки сделать фичу, которая не попала в релиз 5.6.0 из-за недостатка ресурсов при подготовке ветки 5.6. Но зато это первая версия, которая была разработана на GitHub после того, как Atlassian заявил о запланированном удалении Hg-репозиториев с BitBucket-а. Так что теперь дальнейшее развитие SObjectizer-а и so5extra будет происходить на GitHub-е, а SouceForge будет служить зеркалом для тарболлов.

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

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

Ну, например, время от времени высказывается сожаление о том, что SObjectizer завязан на реализацию многопоточности из C++ной стандартной библиотеки. Т.е. на std::thread, std::mutex и вот это вот все.

У нас есть, как минимум, две идеи о том, как можно добавить в SObjectizer возможность использовать свои средства работы с многопоточностью. Но это потребует весьма серьезной переработки SObjectizer-а и мы не хотим идти на такие траты, если это никому не нужно. А вот если кому-то это действительно необходимо, скажем, чтобы использовать SObjectizer в каком-то специфическом окружении, то эту тему можно всерьез пообсуждать.

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

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

Сообщить нам о том, чтобы вы хотели видеть в SObjectizer-е можно через Issues на GitHub, соответствующую Google-группу, Feature Requests на SourceForge. Так же, напомню, что наша компания осуществляет поддержку SObjectizer-а и so5extra (как и других наших продуктов). Так что если вы хотели бы иметь кастомизированную версию SObjectizer-а под свои нужды или вам нужна наша помощью в разработке вашего продукта, то с нами всегда можно договориться ;)

среда, 4 сентября 2019 г.

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

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

Мертвые не умирают (The Dead Don't Die, 2019). Укуренный фильм про зомби от укуренного режиссера, известного своими укуренными фильмами. Зайдет точно не всем. Поэтому рекомендовать не могу. Мне показался слишком скучноватым, хотя некоторые моменты улыбнули.

Мышеловка (4x4, 2019). Аргентино-испанская попытка снять драму+триллер на остросоциальную тему. Получилось не очень. Хотя, возможно, это просто в наших палестинах уровень преступности пока еще не достиг такого уровня, как в Испании, поэтому острота поднятой в фильме проблемы не ощущается.

Люди Икс: Тёмный Феникс (Dark Phoenix, 2019). Наверное, достаточно добротное продолжение серии фильмов про людей Икс. Но очень уж скучное, чуть не заснул при просмотре. Хотя снято все красиво, этого не отнять.

Форсаж: Хоббс и Шоу (Fast & Furious Presents: Hobbs & Shaw, 2019). Настолько тупая и невероятная сказочка, что на ее фоне даже фильмы про Джеймса Бонда начинают казаться документальными. Отчасти это компенсируется юмором и красивой актрисой в главной женской роли, но лишь отчасти.

Игра Ганнибала (Nomis, 2018). Просто удивительно, как можно было собрать такой звездный актерский состав и снять такое унылое и скучное говно.

вторник, 3 сентября 2019 г.

[prog.flame] Отличная статья: "How to Build Good Software"

Из этих наших интернетиков принесло ссылку на отличную статью под названием "How to Build Good Software". Статья капитанская. Для тех, кто варится в разработке софта не первый десяток лет, там ничего нового или незвестного нет. Просто хорошая выжимка вещей, продиктованных самим здравым смыслом.

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

Для меня прям бальзамом на душу прозвучало несколько пунктов в статье. Во-первых, про то, что уход разработчиков несет для компании невосполнимые потери в виде потери знаний, которые нигде и никак не были зафиксированы (а зафиксировать все в принципе невозможно). Тут я не буду проявлять скромность и дам ссылку на свой собственный пост в этом же блоге восьмилетней давности как раз на тему важности этих знаний: [prog;work;thoughts] Прибавка к зарплате “за выслугу лет” программистам, да и не только….

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

В общем, статья хорошая. Прочитать ее полезно. А тем, у кого меньше 10 лет в разработке софта за плечами, так и обязательно ;)

среда, 28 августа 2019 г.

[comp.notebooks] Продолжаю многострадальную тему обновления ноутбука...

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

Все идет к тому, что скрепя сердцем от Asus X570UD придется тем или иным способом избавиться. Не срастается у меня с ним что-то. Экран замечательный, мощности, в принципе хватает, SSD быстрый. Но вот не мобильное это решение для меня оказалось. Вот совсем. Плюс к клавиатуре так и не привык (хотя работаю я на нем совсем мало). Так что для работы не подошел. Фотографии обрабатывать или кино смотреть -- просто замечательно, особенно на специальной подставке. Но т.к. я к фотографии месяцами не притрагиваюсь, то оказывается этот замечательный агрегат без дела.

Посему муки выбора основной рабочей лошадки продолжаются. Причем, судя по анализу того, что и как приходится делать, в пределе нужно два ноутбука. Один под Windows (для Office, для беспроблемного сопряжения с принтерами/сканерами в офисе/дома, для обработки фото и пр. вещей), второй под Linux (для программирования и тестирования). Ибо плотно поработав в последние 3-4 месяца с Linux-ом на реально железе возвращаться на Linux под виртуалками очень не хочется. А если ноутбуков будет два, то весьма критичным будет их размер и вес, т.к. время от времени я таскаю из офиса домой сразу два ноута. И если вес каждого из них до 1.5кг, то с этим проблем нет. А вот если каждый весит под 2кг, да еще и здоровый+тяжелый блок питания у каждого, то как-то кисло выходит. Ну и, в случае замены сперва одного ноута, а затем и второго, вопрос цены каждого из них становится совсем не праздным.

Так же меня не впечатлила производительность современных низковольтных процессоров, вроде Core i5-8250U или i7-8550U, у которых частоты, номинально, могут скакать более чем в два раза. Но, по факту, из-за тротлинга процессоры все равно до своей максимальной производительности не добираются практически никогда. Поэтому, по субъективным впечатлениям, я не вижу заметного прироста скорости выполнения моих повседневных задач когда пересаживаюсь с ноутов пяти или семилетней давности на новую машинку. А тот прирост, который есть, возможно, в большей степени обусловлен современным SSD.

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

Поэтому в качестве основных вариантов я сейчас рассматриваю дешевые ноутбуки, у которых минимальная частота процессора изначально выше 2GHz. Например, это совсем дешевый HP 240 G7 или две модели чуть подороже: HP 14 и Lenovo IdeaPad 530s-14ARR на AMD Ryzen. При этом на HP 14 должна быть более удобная клавиатура, а у IdeaPad 530s -- IPS-ная матрица.

Но вот на чем остановиться пока так и не выбрал. Хорошо хоть, что пока обе рабочие машины остаются в строю и позволяют решать срочные и не очень задачи. Коих, к сожалению, прибавилось после того, как Atlassian объявил о планах по удалению всех Hg-репозиториев в следующем году. Вроде бы времени еще много, но это только кажется.

Поэтому план такой: доэксплуатировать то, что есть в наличии, а потом, когда уже совсем припрет, прикупить что-то из категории "дешево, но сердито". Кстати, никому Asus X570UD (i7-8550U, 8GiB, 256Gb SSD + 1000Gb HDD, 15.6" IPS 3840x2160 + GeForce GTX 1050 4GiB) не нужен? В отличном состоянии, гарантия "5-го элемента" еще в течении 11 месяцев. Отдам не дороже 2000 BYN ;)

суббота, 24 августа 2019 г.

[work.f*ck] О трудоемкости/стоимости SObjectizer-а на простом примере

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

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

среда, 21 августа 2019 г.

[work.sadness] Поддержку Mercurial удаляют с BitBucket-а. Полностью. Что в этом самое плохое?

Вчера получил письмо счастья от Atlassian, в котором говорится об удалении поддержки Mercurial-а и всех Mercurial-репозиториев с BitBucket-а к 1-му июня 2020-го года:

After much consideration, we've decided to remove Mercurial support from Bitbucket Cloud and the API. Mercurial features and repositories will be officially removed from Bitbucket and its API on June 1, 2020.

Полный текст этого печального анонса можно увидеть здесь.

Свое первое возмущение по этому поводу я уже высказал вчера в грубой форме в FB. Но это все лирика. Физика в том, что "just a business". Atlassian владеет BitBucket-ом, вкладывает в его поддержку свои деньги и имеет полное право делать то, что им выгодно, наплевав на мнение 1% своих пользователей. Тем более тех пользователей, которые пользуются этим сервисом бесплатно.

Но если приглушить эмоции, то самое плохое в этом то, что Atlassian тупо удалит все Mercurial репозитории, включая все, что там было, вроде issues, Wiki, артефактов в секции downloads и т.д. Т.е. исчезнет не только код, но и вся сопутствующая база знаний, которая была накоплена вокруг кода.

И вот эта сторона решения Atlassian-а мне непонятна. Хостинг исходных текстов -- это специфическая тема. Люди прибегают к подобным хостерам (будь то GitHub, BitBucket, SourceForge, GitLab или еще что-то) как раз для того, чтобы сделать результаты своих трудов доступным для всех желающих на долгое время. Какой-нибудь древний проект на SourceForge, который уже 15 лет не развивается, все равно доступен и информация оттуда может быть получена даже если автор этого проекта уже давным-давно от проекта отошел (а может автора уже и в живых нет).

Именно в этом ценность открытых хостингов. Я сегодня могу столкнуться с какой-то специфической проблемой, поиск решения которой может привести к старому issue на заброшенном проекте, где проблема и ее возможные решения обсуждаются. Это возможно и такое время от времени происходит, особенно если к тебе на суппорт попадает какое-нибудь древнее легаси. Но возможно это благодаря тому, что хостеры вроде SourceForge или GitHub продолжают хранить проекты, которые давным давно умерли.

В конце-концов, для OpenSource основной смысл хостеров типа SourceForge и GitHub именно в том, что там хранится все, что когда-то там было создано.

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

И вот этого вот решения я понять не могу.

Экономически не выгодно вам пилить поддержку Hg в своей хостинговой платформе? OK. Перестаньте это делать. Переведите все существующие Hg проекты на BitBucket-е в режим read-only. Пусть все, что люди ранее сделали на вашей платформе... Нет, даже не так, а вот так: все, что люди ранее сделали на ВАШЕЙ платформе останется доступным для всех желающих.

Понятно, что даже на саппорт read-only репозиториев придется тратить какие-то деньги. И если это для Atlassian-а настолько серьезные деньги, то можно было бы ограничить время существования read-only репозиториев. Скажем, всего 5 лет. Потом навечно в /dev/null. Но хотя бы в течении этих пяти лет ссылки на репозитории, issues, Wiki, тарболлы и пр., которые в невероятном количестве раскиданы по всему Интернету, будут оставаться валидными.

PS. Ну вот честно не могу даже вообразить себе степень эффективности менеджеров Atlassian-а, принявших решение тупо убить проекты с Hg репозиториями вместо того, чтобы перевести их в read-only mode. Хотя бы лет на пять. Какой-то, блин, контрольный самострел в голову.

понедельник, 19 августа 2019 г.

[prog.flame.c++] Dropbox выставляет свою Djinni на мороз

Кстати говоря, в делах и заботах упустил из виду вот эту публикацию: (Не очень) скрытые издержки общей кодовой базы iOS и Android

Между тем штука значимая.

Я вот несколько лет то тут, то там рассказываю про такую область применения C++, как написание "ядра" кросс-платформенных приложений. Типа того, что бизнес-логика пишется на плюсах, а GUI и какие-то штуки по интеграции с системно-зависимыми сервисами на родных для платформы языках (вроде Java на Android-е, Objective-C/Swift на iOS, C++ или .NET на Windows).

И в качестве примера приводил разработку Djinni от Dropbox-а.

А вот, оказалось, что Dropbox такой подход к кроссплатформенности запарил и они от него отказались.

В статье, однако, как мне показалось, внятно сформулирован только один раздел, под названием "Оверхед на найм, обучение и удержание разработчиков". Тут как раз ничего вопросов не вызывает. Сперва была хорошая команда толковых C++ников, которые этот подход опробовали и продвинули внутри компании. А потом разошлись кто куда. И заменить их не кем. Поэтому продолжать писать на C++ с должным уровнем качества уже некому.

Остальные же причины, в частности, про оверхед пользовательских фреймворков и библиотек, вызывают недоумение. Никто не заставлял Dropbox делать свою собственную библиотеку для работы с Json в С++. Очень похоже на NIH-синдром и его последствия.

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

суббота, 17 августа 2019 г.

[comp.notebooks] Минутка дыбра: продолжение истории про выбор ноутбука

Развитие темы, начатой на прошлой неделе. Я прислушался к мнению уважаемых френдов, которые сказали, что FullHD разрешение -- это уже вчерашний день и нужно что-то принципиально получше. В итоге приобрел 15.6" ноутбук с UHD разрешением (3840x2160): Asus X570UD. Если кому-то интересно почитать о моих текущих впечатлениях, то милости прошу под кат.

пятница, 16 августа 2019 г.

[prog.flame] Ну не могу не утащить великолепную цитату в склерозник. Про RAII в виде создания процессов

Ну прекрасно же! Просто прекрасно. Ни добавить, ни убавить.

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

Взято отсюда. Это человек решил вступить в спор о том, чего не хватает в чистом С, в частности об отсутствии в C классов и RAII.

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

среда, 14 августа 2019 г.

[prog.c++] Быть или не быть tls_inspector-у в RESTinio? И если быть, то каким?

В комментариях к одной из статей про RESTinio на Хабре прозвучала идея сделать объект tls_inspector для проверки TLS-ных подключений. И не только проверки, но и просто извлечения из сертификата клиента различной полезной для сервера информации.

Дошли руки заняться этой темой. Но есть ощущение, что блин получился комом. Если кому-то интересно, то суть я попытался описать здесь: https://github.com/Stiffstream/restinio/issues/44
Там же можно высказать и свое "фи". Хотя его можно высказать и прямо здесь ;)

вторник, 6 августа 2019 г.

[comp.notebooks] Минутка дыбра: очередной приступ поиска нового ноутбука :)

Бывает у меня периодически такое специфическое состояние: я начинаю выбирать себе новый ноутбук. Иногда просто потому, что время идет, моей "основной" машинке, уже больше пяти лет. А "резервной" уже около семи. Иногда потому, что на обоих машинах время от времени что-то оказывает. Так, последний приступ выбора ноутбука был в районе Нового Года, когда на "основной" стала слишком часто проявляться его родовая травма в виде спонтанных самовыключений, а на "резервной" начала выходить из строя клавиатура и аккумулятор перестал держать заряд. Но тогда удалось обойтись без приобретения новой машины путем латания уже имеющихся. Однако, прошло какое-то время, латки поизносились и вновь стал мучать вопрос о приобретении нового ноута, который сможет поработать в режиме 12/7 следующие несколько лет.

Еще один фактор, толкающий на поиск нового ноута -- это то, что годы берут свое и зрение от этого лучше не становится. Экран в 13.3", особенно с FullHD разрешением -- это уже тяжеловато, при том, что пялится в экран приходится по многу часов в день. Разрешение 1399x768 на 13.3" намного более щадящее, но зато есть другая проблема: сложно ориентироваться на экране, когда там открыто несколько десятков окон. Покупка внешнего монитора не вариант, т.к. тогда теряеся мобильность, а это именно то, ради чего мне ноутбук и нужен.

Дополнительный забавный момент в том, что в последние месяца три "резервная" машинка, которая у меня под Linux-ом, стала для меня основной рабочей станцией. Т.к. практически все сейчас делается под Linux-ом. А в Windows я захожу лишь по необходимости: с документами в MS Office разобраться, провести проверки под Visual C++, поработать в Lightroom-е, если где-то что-то заснял. Так что сейчас я практически линуксоид ;)

Выбор оказывается весьма непростой.

Основные требования, которые должны быть удовлетворены в обязательном порядке -- это, минимум 8GiB RAM, 4-е ядра (причем нормального Core i5/7 или Ryzen, а не какого-нибудь маломощного мобильного Pentium-а с частотой 1.1GHz), SSD диск от 128Gb, матовый экран.

Еще один серьезный момент: производитель. Из того, что широко представлено у нас, я доверяю разве что HP и Lenovo, плюс, в несколько меньшей степени, Asus и Dell.

Пожалуй, главный сдерживающий фактор -- это размер и вес. 17" экран с FullHD разрешением, наверное, был бы для меня вполне подходящим выбором. Но, боюсь, в мой рюкзак он не влезет. Да и таскать с собой каждый день туда-сюда 3кг вместо 1.5кг как-то не воодушевляет. Я, конечно, товарищ немаленький и доходягой вроде не являюсь, но лишний груз взваливать на спину не хочется :)

И если с размером и весом проблемы были ожидаемы, то неожиданными оказались вот такие факторы:

  • неудобные клавиатуры. Отсутствие отдельной клавишы Ins -- это обычное дело. Так же, как и кнопок PgUp/PgDn и Home/End. Причем, если для 13.3" или даже 14" ноута это еще понять можно (хотя можно посмотреть на HP ProBook 440 G6, например, там с нужными кнопками все нормально), то вот для 15" или 17" ноутов, в которые умудряются впихивать еще и блок цифровых клавиш отсутствие отдельной Ins -- это что-то за гранью моего понимания;
  • наличие USB 2.0 разъемов на моделях от 2017, 2018 и даже 2019-го годов. Скажем, ноут от 2018-го у которого два USB 2.0 и всего один USB 3.0 -- это вообще что такое?

При этом всем я ориентируюсь на весьма бюджетный сегмент -- плюс минус 1K USD. Ибо мне нужен рабочий инструмент, который я буду гонять и в хвост, и в гриву, и который не должно быть жалко, если я где-то долбану его по дороге или уроню на него что-нибудь, или он тупо сдохнет под непосильной нагрузкой :) Типа премиуальный/имиджевый ноутбук у меня был, это совсем другая история.

Благо, рабочих лошадок стоимостью между $700 и $1000 с 4-х ядерными Core i5 8-го поколения, 8GiB RAM и SSD на 256GB не так уж и мало. Например, HP ProBook 440 G6 6BN87ES с параметрами: Intel Core i5 8265U, 8GiB RAM DDR4, SSD 256GiB, FullHD IPS-дисплей, металлический корпус и вес порядка 1.6кг. Стоит такая машинка на данный момент порядка $800. Жаль только, что 14" :(

Пока в short-list-е у меня две модели от Lenovo: ThinkPad e590 и IdeaPad S340-15IWL. В пользу ThinkPad говорит IPS-ная матрица, намного более удобная для меня клавиатура (защищенная от протечек при том). А в пользу IdeaPad немного меньший размер и заметно меньший вес.

Но в обоих вариантах смущает то, что FullHD на 15.6" экране. С учетом того, что ноут мне нужен для работы с кодом в Linux-е, это настораживает. ИМХО, слишком мелкий пиксель. Хотя шрифты можно увеличить, да. Но все равно как-то мелковато.

В связи с этим хочу спросить у тех, кто работает с ноутами-пятнашками с FullHD разрешением: как вам? Нормально или размер пикселя все-таки хотелось бы побольше?

PS. Жаль, что я завязан на C++. Программировал бы на Go, мог бы обойтись чем-то вроде вот такого. С дополнительным SSD, естественно ;)

четверг, 1 августа 2019 г.

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

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

Та еще парочка (Long Shot, 2019). Смотрибельно. Примитивно, предсказуемо. Но местами смешно. Плюс присутствие красавицы Шарлиз Терон компенсирует какие-то мелкие недостатки. И не очень мелкие недостатки тоже ;)

В упор (Point Blank, 2019). Неоднозначные впечатления. С одной стороны, смотрибельно. С другой стороны, авторы пытаются нагнетать драму и эмоциональное напряжение, но в итоге все оказывается каким-то легкомысленным.

Хладнокровный (Cold Blood Legacy, 2019). Халтура. Даже удивительно, как Жан Рено согласился на участие в таком.

Искусство обмана (Lying and Stealing, 2019). Н-у-у о-о-о-чень с-к-у-у-у-чный ф-и-и-и-льм. Вот буквально: смотришь, а на экране какая-то нудятина, которая все никак не закончится.

Клуб анонимных киллеров (Killers Anonymous, 2019). Откровенная дрянь. Главная загадка: что там делает Гари Олдман?

Годзилла 2: Король монстров (Godzilla: King of the Monsters, 2019). Редкий бред. Не смотреть ни в коем случае.

суббота, 27 июля 2019 г.

[work.thoughts] Мысля насчет расценок в зависимости от языка программирования

В последнее время, когда приходится писать код, делаю это либо на C++17, либо на C++14, либо на C++11. Либо, внезапно, на чистом C. C++98 уже давно не попадалось.

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

Но к чему я этим решил поделиться? А вот к чему.

Похоже, что нужно выстраивать ценник в зависимости от степени свежести стандарта языка программирования. Скажем, есть базовая цена для C++17 (для наших еб*ней с прицелом на заказчиков из РФ -- это где-то $25/hour для проекта от двух-трех месяцев длительностью без горящих сроков).

Тогда для C++14 будет базовая цена + 5%.

Для C++11: базовая цена + 25%. А если нужно жить с GCC ниже 4.8 или MSVS2013, то + 50%.

Для C++98: базовая цена * 2.

Для чистого C: базовая цена * 3.89. В случае, если заказчик согласен на частичный рефакторинг с постепенным затаскиванием C++ных частей в C-шную кодовую базу (или постепенный перевод с C на C++), то базовая цена * 2.17.

Ибо нех*й.

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

PS. Если кто-то остался один на один с древним C-шным или C++ным кодом, без которого вам не обойтись, но с которым вы не знаете, что делать, то вам сюда. И да, это реклама. Проплачена мной.

пятница, 26 июля 2019 г.

[prog.c++] rotor: библиотека, разработанная под влиянием SObjectizer-а

Полку акторных фреймворков для C++ прибыло!

Собственно, вот: rotor. Автор пробовал использовать SObjectizer, но у SObjectizer-а нет интеграции с wxWidgets, а интеграция с Asio находится под двойной лицензией. Поэтому автору показалось проще сделать свое решение. Более подробно о причинах можно прочитать здесь.

Безотносительно того, как я сам оцениваю объективность/субъективность причин, толкнувших на создание rotor-а, хочется пожелать автору удачи. Во-первых, потому, что C++у нужно больше фреймворков, хороших и разных. Во-вторых, потому что это только начало. Выкатить первую версию и даже развивать ее в первые несколько лет не проблема. А вот дальше сложнее. Особенно с учетом того, что универсальные акторные фреймворки в мире C++ как-то особо не взлетают.

Ну а меня впечатляет другое: как-то незаметно для меня SObjectizer превратился в большой и сложный инструмент. Настолько, что кто-то уже хочет чего-то полегче. Ну это типа ты сделал текстовый процессор уровня Microsoft Word, а пользователи говорят, да не, нам бы чего-то не сложнее WordPad-а :)

суббота, 20 июля 2019 г.

[prog.c++] Идея развития темы, начатой в статье "A declarative data-processing pipeline on top of actors? Why not?"

Давеча опубликовал на Хабре большую статью на английском языке "A declarative data-processing pipeline on top of actors? Why not?", в которой описал старый, но доведенный "до ума" пример make_pipeline из состава SObjectizer-а. К самой статье Григорий Демченко задал интересные вопросы в комментарии. Плюс на Reddit-е подсунули ссылку на (как мне показалось) недоделанную и полузаброшенную библиотеку RaftLib.

В общем, появилось навязчивое желание сделать продолжение этой темы.

По сути, тема создания пайплайнов (или графов в общем случае) обработки данных на C++ состоит из двух частей. Можно сказать, что есть верхняя и нижняя части проблемы.

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

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

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

среда, 17 июля 2019 г.

[prog.flame] Почему Rust может быть намного более пригоден для прикладного программирования, чем C++

Несколько запоздалое дополнение к двум постам с прошлой недели (раз, два). Хочу немного поговорить о неоднократно услышанном от Rust-евангелистов мнении, что Rust отлично подойдет не только для системного (и околосистемного) программирования, но и для прикладного.

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

Прежде чем пойти дальше отпрыгнем в сторону и попробуем хоть как-то определить само понятие "прикладного программирования". По большому счету к прикладному программированию можно отнести все, что не касается системного и низкоуровневого программирования. Т.е. если код не решает каких-то специфических задач, интересных только программистам (ядро ОС, компилятор, линкер, MQ-шный брокер, сервер БД, утилита типа grep и т.д.) или не управляет каким-то оборудованием (вроде бортового ПО автомобиля или самолета), то это прикладное ПО. К сожалению, в этом случае в "прикладное ПО" попадает слишком большой спектр софта: скажем, от Microsoft Word или Adobe Lightroom до склепанного на коленке в Wordpress сайта-визитки. Но есть подозрение, что если попытаться конкретизировать термин "прикладное ПО", то возникнет ощущение насильственной подгонки условий под нужный результат. Посему более жестких условий накладывать не будем.

Итак, есть тезис о том, что Rust отлично подойдет для прикладного программирования...

вторник, 16 июля 2019 г.

[prog.sadness] Похоже, разработчики D решили закопать свой язык еще глубже

За последние месяцы я несколько подзадолбался как с разработкой на C++, так и с общением с придерживающимися разных взглядов C++никами, так и c продвижением наших C++ных разработок в сильно сегментированном C++ сообществе. Настолько, что стал уже мечтать о том, чтобы закрыть ближайшие "долги" по работам вокруг SObjectizer-а и устроить себе отдых от C++. Пропрограммировать что-то для души на чем-то более современном и удобном, чем C++.

На D.

А вот сегодня на HackerNews увидел ссылку на статью Вальтера Брайта (это автор D и его основной разработчик) про возможность добавления в D механизмов Ownership и Borrowing из Rust-а. Смысл статьи в том, что изначально Брайт думал, что borrow checker из Rust в D не запихнуть, но потом у него появились идеи, которые Брайту кажутся вполне себе реализуемыми. Поэтому Брайт начинает активно копать в этом направлении.

Ну что тут сказать. Один раз Брайт и Ко уже основательно поднасрали своему детищу. Это кода в 2008-го году, всего через полгода после официального релиза D 1.000 было заявлено, что начинаются работы над D2, который будет несовместим с D1. Сказано это было в тот момент, когда вокруг D не было никакой существенной экосистемы и количество нормальных библиотек для D измерялось, в лучшем случае, несколькими десятками.

Да, D2 получился гораздо более интересным и мощным языком, чем D1. Но лет через шесть после D 1.000. И, по факту, он появился уже тогда, когда окно возможностей для D захлопнулось благодаря C++11/14, Go, хайпу вокруг Rust-а. Так что D отличный язык для небольших проектов маленьких команд и энтузиастов. Но широкого применения ему, увы, уже не светит.

А тут в D хотят впихнуть еще одну мегафичу. И мне непонятно нахрена это нужно делать :(

Ну вот основная фишка в том, что это продвинутый язык с GC для нейтива. И как раз GC дает D те преимущества, о которых C++никам остается только мечтать, если на C++ пытаться разрабатывать что-то более-менее высокоуровневое.

Казалось бы: ну и развивайте D как язык с GC. У вас и в этой области работы будет выше крыши. Зачем вы еще куда-то лезете? Делаете GC отключаемым, придумываете какой-то betterC... Теперь вот еще и borrow checker в язык затаскиваете...

Ну вот явно "чувство меры" -- это не то, что свойственно разработчикам D.

Пичалька, что еще скажешь. Вот так и разрушаются мечты :(

пятница, 12 июля 2019 г.

[prog.flame] Пятничное дополнение ко вчерашнему посту. Снова про Rust

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

А что будет, когда на Rust-е начнут программировать разработчики уровня сильно ниже среднего?

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

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

Так, на примере C++ видно, что есть языки, которые не прощают тупость разработчика.

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

Тогда как языки Java и Go зарекомендовали себя просто отлично с этой стороны. Высказывание "на Java можно посадить толпу индусов" -- это уже давно не фигура речи, а многократно подтвержденный успешный менеджерский опыт. Причем "индус" здесь не национальность, а уровень квалификации.

Так вот, мне не понятно, что будет происходить с разработкой на C++, когда туда придут персонажи, вроде RussianFellow с RSDN-а. Чтобы было понятно, о чем речь, вот замечательный образчик. И если кто-то думает, что подобные персонажи -- это редкость, то смею вас разуверить. Не редкость.

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

Имхо, вариант Haskell-я, когда посредственности в этот язык просто не идут, здесь не прокатит. Т.к. Haskell в силу разных причин никогда и не мог претендовать на широкое использование. В отличии от Rust-а.

Так что будет интересно посмотреть на то, что произойдет. Выпрямит ли Rust-овский компилятор растущие из жопы руки? Или этот самый компилятор наеб*т посредством расставления unsafe в коде, ибо дедлайны, нужно фичи в прод выкатывать, а не ублажать borrow checker.

четверг, 11 июля 2019 г.

[prog.flame] Предлагаю новый слоган для D: "Fast as C++, safe as Rust, easy as Java"

Намедни в LOR-овском срачике сформулировал свое впечатление от наблюдений за тем, кто, как и откуда переходит на Rust. На мой взгляд, в Rust идут люди, которые всю жизнь программировали на безопасных языках с виртуальной машиной. Ну там Java, Python, Ruby, JavaScript, Erlang, Clojure и т.д. А так же C++ники, которые толком C++ не освоили, а уж о том, что такое современный C++, вообще не имеют никакого понятия.

А потом довелось прочитать серию постов небезызвестного своими "плачами Ярославны" НикиТонского: "С высоты", "С высоты-2" и "С высоты-3". И еще более утвердился в том, что мои наблюдения более-менее коррелируют с действительностью.

вторник, 9 июля 2019 г.

[prog.c++] Что-то затупил с выписыванием условия для SFINAE

Стоило отвлечься на пару недель на написание документации и статей, как остаточные знания C++ улетучились из головы и случились жуткие тормоза при попытке написать условие для SFINAE :(

Нужно было вот что: в шаблонный фабричный метод передается ссылка на контейнер (или что-то, что притворяется контейнером, какой-нибудь range, к примеру). Нужно, чтобы этот шаблонный фабричный метод попадал в рассмотрение компилятора только если передали ссылку на контейнер/range. Для этого я решил написать проверку того, что у контейнера есть методы begin/end, и что при разыменовании итератора, возвращенного begin-ом, получается нужный мне тип.

Затык случился при попытке написать проверку на наличие begin/end. Вроде как в C++17 нет штатных средств проверить, что decltype(std::declval<const Another_Container &>().begin()) является валидным типом. Т.е. не нашел в type_traits чего-то вроде is_valid_v<constexpr-expr>. Пришлось извращаться вот таким образом:

templatetypename Another_Container >
static std::enable_if_t<
      !std::is_same_v< Container, Another_Container >
      && !std::is_same_v<
            decltype(std::declval<const Another_Container &>().begin()),
            void >
      && !std::is_same_v<
            decltype(std::declval<const Another_Container &>().end()),
            void >
      && std::is_same_v<
            std::decay_t<
                  decltype(*(std::declval<const Another_Container &>().begin())) >,
            mbox_t >,
      mbox_t >
make(
   environment_t & env,
   const Another_Container & destinations )
   {
      return make( env, destinations.begin(), destinations.end() );
   }

Т.е. сравнивать тип итератора, возвращаемого begin/end, с void. Ведь итератор, в принципе, не может иметь тип void. Поэтому если begin/end есть, то возвращать они должны не void.

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

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

templatetypename Another_Container >
static std::enable_if_t<
      !std::is_same_v< Container, Another_Container >
      && std::is_convertible_v<
            decltype(
               ++std::declval<
                  std::add_lvalue_reference_t<
                     decltype(std::begin(std::declval<const Another_Container &>()))>
                  >()
               == std::end(std::declval<const Another_Container &>()) ),
            bool>
      && std::is_same_v<
            std::decay_t<
                  decltype(*std::begin(std::declval<const Another_Container &>())) >,
            mbox_t >,
      mbox_t >
make(

Здесь сделано упрощение + поддержка C-шных массивов + несколько дополнительных проверок, которых не было ранее, а должны были бы быть. И, что самое интересное, это даже VC++ компилируется (как VS2019, так и VS2017).

Upd.2 У варианта с SFINAE обнаружилось два серьезных недостатка. Первый, который был виден изначально, это отсутствие поддержки ADL. Т.е. если Another_Container -- это какой-то пользовательский тип, для которого пользователем определены собственные begin/end функции, то SFINAE бы его забраковал. Поскольку внутри SFINAE используются std::begin/std::end. И как внутри условия SFINAE разбираться с ADL без создания каких-то дополнительных вспомогательных сущностей -- это отдельный квест.

Второй недостаток -- это неспособность Doxygen-а сгенерировать документацию для метода с навороченными условиями SFINAE. Показанный в первом апдейте вариант кода Doxygen не может переворить и просто не включает такой make в итоговую документацию :(

Посему в итоге отказался от SFINAE, а все проверки перенес внутрь метода в static_assert-ы. Получилось что-то вроде:

templatetypename Another_Container >
static mbox_t
make(
   environment_t & env,
   const Another_Container & destinations )
   {
      using std::begin;
      using std::end;

      // Ensure that destinations if a container or range-like object
      // with mbox_t inside.
      static_assert(
         std::is_convertible_v<
            decltype(
               ++std::declval<
                  std::add_lvalue_reference_t<
                     decltype(begin(std::declval<const Another_Container &>()))>
                  >()
               == end(std::declval<const Another_Container &>()) ),
            bool>,
         "destinations should be a container or range-like object" );

      static_assert(
         std::is_same_v<
            std::decay_t<
                  decltype(*begin(std::declval<const Another_Container &>())) >,
            mbox_t >,
         "mbox_t should be accessible via iterator for destinations container (or "
         "range-like object" );

      return make( env, begin(destinations), end(destinations) );
   }

PS. Ну и современный C++ в очередной раз оставил впечатление вроде "ну круто, чё, а нельзя ли все тоже самое, но раза в полтора-два попроще?". Так что ждем C++20 с концептами.

понедельник, 1 июля 2019 г.

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

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

Отель Мумбаи: Противостояние (Hotel Mumbai, 2018). Добротно снят. В принципе, понравился.

Однажды в Стокгольме (Stockholm, 2018). Любопытный фильм, стилизованный под эпоху 1970-х. Этим, наверное, и интересен в первую очередь. Как будто не от мира сего в хорошем смысле этого слова.

Битва за Землю (Captive State, 2019). Мне понравилось. Но фильм специфический. В нем создается своеобразная атмосфера, в которую хорошо вписываются главные герои фильма. Именно это мне в картине и понравилось. Однако, если вы ждете динамичного экшена, то фильм вас разочарует.

Загадочное убийство (Murder Mystery, 2019). Ну так себе средней руки фильмец. Местами смешно. На Дженнифер Энистон все еще приятно смотреть. Плюс Дэни Бун в придачу. Проходная комедия, но посмотреть можно.

Люди в черном 4 (Men in Black International, 2019). Полное разочарование. Весь фильм -- стандартные клише. Никакой интриги. Крис Хэмсворд играет полного дегенерата. Смешного мало. Спецэффекты так себе. В общем, понятно, что киностудия захотела перезапустить успешную в прошлом франшизу, но жидко обгадилась.

Шафт (Shaft, 2019). Скучно. Экшена мало. Тупизма много. Негров слишком много. Посмотреть можно разве что если больше нечего смотреть.

Домино (Domino, 2019). В страшном сне не могло привидится, что Брайн Де Пальма, автор "Лица со шрамом", "Путь Карлито" и "Миссия: невыполнима", опустится до такого шлака. А вот поди ж ты :(

План побега 3 (Escape Plan: The Extractors, 2019). Говнофильм. Но, в отличии от второй части, эту я хотя бы смог досмотреть. Ощущение, что снимался по следующему принципу: у нас есть вот столько-то героев, пусть эти будут хорошими, а вот эти -- плохими. Пусть вот этот будет выбивать зубы вот этому, а вот этот будет драться с вот этим. Ок, боевые сцены засняли, теперь заполним пространство между ними каким-то невероятным бредом.

вторник, 25 июня 2019 г.

[prog.c++] Кому-нибудь будет интересен еще один доклад про акторов и их применимость/реализуемость в C++?

Мне прислали приглашение подать доклад на конференцию C++ Russia 2019 Piter, которая пройдет в Питере 31-го октября и 1-го ноября. И я нахожусь в задумчивости по поводу темы доклада с которым можно было бы достойно выступить.

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

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

А так же добавить сюда информацию о том, как модель акторов может быть реализована в C++. Ну, например, как могут быть в принципе представлены акторы (нити, сопрограммы, объекты с коллбэками). Как может происходить извлечение и обработка сообщений (ручной вызов receive актором или автоматический вызов коллбэка). Как может происходить работа с сообщениями (аллокация в момент отсылки, преаллокация, аллокация с отложенной деаллокацией, простой FIFO порядок или selective-receive/stashing). Отказоустойчивость C++ приложений с акторами. Защита акторов от перегрузок. Распределенность для акторов (прозрачная или непрозрачная, из коробки или нет). Насколько черным должен быть тот ящик, который выступает в качестве акторного фреймворка (т.е. насколько просто в него заглянуть и понять, что происходит). Насколько просто тестировать акторов и кто/как может в этом помочь.

И, главное, чтобы этот рассказ не был привязан к какому-то одному конкретному инструменту. Ссылки на то, что есть в наличии в QP/C++, CAF, SObjectizer и т.п., возможны, но разве что как иллюстрации.

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

Часть этих вопросов уже рассматривалась, например, на Corehard Autumn 2017. Но там рассматривался, в основном, концептуальный аспект, без привязки к особенностям реализации. А когда мы говорим об акторах в C++, то без привязки к реализации не обойтись. Очень уж специфический язык C++ и очень уж сильно сегментировано его комьюнити (об этом речь шла на C++ Russia 2018, но там не освещался вопрос полезности/бесполезности акторов). Поэтому хочется выдать материал в максимально сжатом и концентрированном виде.

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

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

пятница, 21 июня 2019 г.

[prog.c++] В склерозник: список встраиваемых HTTP-серверов для C++

Время от времени приходится то там, то там рассказывать людям, что в мире C++ есть ряд готовых к использованию встраиваемых HTTP-серверов. И дабы этот список было проще искать, решил зафиксировать его в виде блог-поста. Итак, что есть:

  • RESTinio. Это наша разработка, в которую наша маленькая команда продолжает вкладывать силы и душу. Соответственно, номер один в списке претендентов. Если вам чего-то не хватает в RESTinio или что-то не нравится, то с нами всегда можно договориться ;)
  • Silicon Framework;
  • Pistache;
  • RestBed. Продвинутый. Но, насколько я помню, был одним из самых тормозных. Плюс он идет под двойной лицензией. Т.е. либо за деньги, либо GPL;
  • served;
  • C++REST SDK. Разработка от самого Microsoft-а. Не знаю, как сейчас, но раньше не отличалась хорошей производительностью под Linux-ами;
  • proxygen от Facebook-а. Традиционно ориентируется на мир Linux-ов, насколько юзабелен за его пределами (тем более под Windows) -- без понятия;
  • Simple-Web-Server (раньше жил на GitHub-е);
  • drogon;
  • CROW. Пожалуй один из самых распиаренных фреймворков такого рода для C++. Но который, вероятно, уже давно приказал долго жить и не развивается с декабря 2017-го.

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

четверг, 20 июня 2019 г.

[prog] Статья на Хабре не про акторы, но в которой можно увидеть хороший пример использования акторов

Вот эта статья от Яндекса на Хабре: "Архитектура сервиса распределённых очередей сообщений в Яндекс.Облаке". И картинка оттуда, демонстрирующая наличие акторов:

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

№1:

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

№2:

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

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

И, как по мне, сама по себе задача разработки системы, вроде YMQ, является отличным примером ниши, для которой могут применяться инструменты вроде Akka, SObjectizer, CAF, Actix и пр. По крайней мере наверняка могу сказать, что заложенные в SObjectizer проектные решения (вроде использования динамической памяти и исключений) не будут стоп-фактором для использования SObjectizer-а в разработке подобного проекта. В отличии от проектов, связанных с настоящими системами жесткого реального времени.

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

Ну а почему бы и нет? Вообще, список подходящих кандидатов окажется небольшой: Java (или альтернативы для JVM, вроде Scala, Kotlin, Ceylon), C#, C++ и Rust. Можно, конечно, взять в рассмотрение еще и чистый C, а так же Go. Но, имхо, стартовать сейчас что-либо на чистом C за пределами системной Linux-овой хардкорщины -- это крайняя степень изощренного мазохизма. Тогда как Go, опять же имхо, не очень хорош для разработки больших и долгоживущих проектов (просто в силу убогости заложенных в этот язык выразительных возможностей).

Так что, по сути, имеем список из Java, C#, С++ и Rust. При этом и у C++, и у Rust-а есть то преимущество, что в погоне за максимальной производительностью можно без проблем опускаться на сколь угодно низкий уровень.

Вот и получается, что есть резоны как для выбора C++, так и для отказа от C++. Посему почему бы и нет?

PS. Динамику, вроде Erlang-а, я не рассматривал. Ибо делать большие системы на динамике -- это другая крайняя степень мазохизма, имхо. Но, наверняка, Erlang или какой-нибудь Elixir можно будет использовать в разработке такого рода системы. Тут вопрос лишь в итоговой ее стоимости. Впрочем, как и в случае C++.

среда, 19 июня 2019 г.

[prog.c++] Послесловие к релизу RESTinio 0.5.1

Давеча мы выпустили очередной релиз RESTinio. RESTinio обзавелся несколькими фичами, о которых нас время от времени спрашивали. Если кому-то интересны некоторые детали реализации, то можно посмотреть вот эту статью на Хабре.

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

Если же новые хотелки озвучиваться не будут, то RESTinio будет оставаться в своем текущем состоянии.

Я бы даже развил эту мысль. Текущие версии наших проектов, будь то RESTinio, SObjectizer/so5extra или json_dto, имеет смысл рассматривать как инструментарий в, скажем так, базовой комплектации. Не факт, что эта базовая комплектация хорошо подходит для ваших условий. И, если подходит не очень хорошо (либо вы думаете, что подходит не очень хорошо), то вы можете обсудить ситуацию с нами. Есть далеко не нулевая вероятность, что наши инструменты смогут быть доработаны так, чтобы удовлетворять вашим требованиям.