вторник, 1 января 2030 г.

О блоге

Более двадцати лет я занимался разработкой ПО, в основном как программист и тим-лид, а в 2012-2014гг как руководитель департамента разработки и внедрения ПО в компании Интервэйл (подробнее на LinkedIn). Поэтому в моем блоге много заметок о работе, в частности о программировании и компьютерах, а так же об управлении.

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

понедельник, 31 декабря 2029 г.

[life.photo] Характерный портрет: вы и ваш мир моими глазами. Безвозмездно :)

Вы художник? Бармен или музыкант? Или, может быть, коллекционер? Плотник или столяр? Кузнец или слесарь? Владеете маленьким магазинчиком или управляете большим производством? Реставрируете старинные часы или просто починяете примус? Всю жизнь занимаетесь своим любимым делом и хотели бы иметь фото на память?

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

суббота, 24 сентября 2016 г.

[prog.c++] Переполенные mchains и доставка отложенных/периодических сообщений

Пока готовил очередную статью для Хабра, выяснил, что в SObjectizer при добавлении message chains (это нечто вроде CSP-шных каналов) был допущен серьезный просчет. Дело вот в чем: mchain-ы могут использоваться для отсылки отложенных и периодических сообщений. Т.е. можно вызывать send_delayed или send_periodic, а в качестве адресата указать mchain. И сообщение "упадет" в этот mchain спустя указанное время.

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

  • можно подождать какое-то время на send-е. Если за это время место в mchain-е освободилось, то просто добавить сообщение в mchain и все. А вот если мы подождали, но места не нашлось, тогда идем к следующему пункту. Впрочем, можно сконфигурировать mchain так, чтобы ожидания вообще не было. Тогда мы сразу же идем к следующему пункту;
  • т.к. места в mchain-е нет, то SObjectizer смотрит на параметр overflow_reaction для mchain и:
    • в случае drop_newest просто игнорирует новое сообщение, которые мы пытаемся добавить в mchain;
    • в случае remove_oldest выбрасывает самое старое сообщение из mchain-а, а новое -- добавляет в mchain;
    • в случае throw_exception выбрасывает самое новое сообщение и генерирует исключение;
    • в случае abort_app просто вызывает std::abort.

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

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

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

Во-вторых, на нити таймера нельзя бросать исключения. В этом нет смысла, т.к. таймер понятия не имеет, что делать с исключением о переполнении какого-то mchain-а. Любое такое исключение просто приведет к вызову std::abort.

Тем не менее, все версии SO-5 с поддержкой mchain-ов, включая последнюю стабильную 5.5.17.1, не учитывают этих ограничений для контекста таймерной нити. И, если пользователь вызывает send_delayed для ограниченного по размеру mchain-а с ожиданием на переполнении и с реакций throw_exception, то когда время доставки сообщения наступит, а mchain будет полон, то сперва нить таймера заснет на этом mchain-е, затем будет брошено исключение, от которого все приложение упадет из-за вызова std::abort.

Такой вот недосмотр.

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

  • если нить таймера обнаруживает, что отложенное/периодическое сообщение идет в переполненный mchain, то ожидание на этом mchain-е не производится, даже если такое ожидание предписано в параметрах mchain-а. Нить таймера просто сразу начнет обрабатывать overflow_reaction. Без каких-либо задержек и ожиданий;
  • вместо throw_exceptio нить таймера выполняет реакцию drop_newest, т.е. простое выбрасывание сообщения, как будто его и не было.

Эти исправления уже реализованы и протестированы. Но в основную ветку я их пока не включил. Хочу послушать другие мнения. Может есть какие-то другие подходы к решению проблемы выполнения overflow_reaction на контексте нити таймера?

пятница, 23 сентября 2016 г.

[business.thoughts] Не понятные для меня вещи в бизнес-стратегии продавцов PVS-Studio

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

Стратегия продвижения PVS-Studio через ресурсы, вроде Habr-а, LOR-а и RSDN, по словам главного разработчика PVS-Studio рассчитана на то, что обычные программисты будут узнавать о такой штуке, как статический анализ и будут проникаться его мощью и полезностью. После чего, проникшись, побегут к своим менеджерам с просьбами прикупить PVS-Studio дабы...

И вот тут начинаются вопросы.

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

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

Прошу не думать, что я противник статического анализа кода. Речь про другое: вот программист прочитал несколько статей о том, какие баги PVS-Studio выловил в том или ином открытом проекте. Как на основании этой информации сделать вывод о том, что для проекта масштаба N килобаксов с такими-то требованиями к качеству ПО покупка PVS-Studio принесет ощутимый результат?

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

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

Второй момент, который так же имеет отношение к вопросу "дабы что?", связан с отсутствием легкодоступной информации о стоимости PVS-Studio. Полагаю, разработчики PVS-Studio смотрят на мир так:

Вот некий разработчик узнал о выгодах статического анализа вообще и PVS-Studio в частности. Радостный побежал к своему менеджеру: "Надо брать!". А менеджер спрашивает: "И во сколько нам обойдется сие счастье?" А разработчик: "Я не знаю, у них цену нужно отдельно уточнять". И менеджер такой: "Нет проблем. Спасибо, что рассказал про PVS-Studio, я с ними сам свяжусь и все выясню".

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

В общем, если бы цена была указана сразу на сайте, то продвижение PVS-Studio "снизу-вверх", как об этом мечтают продавцы сего продукта, было бы проще. Например, цены на Visual Studio, CLion, TBB, Qt, gSOAP или на техподдержку для POCO свободно доступны. Что, по-моему, сильно облегчает разговоры о необходимости их покупки.

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


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

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

[life] Крохоборское ворчание про стоимость билетов до Москвы

Про белорусское экономическое чудо у нас уже как-то не говорят, хотя отдельные его проявления местами доставляют. Взять, например, стоимость билетов от Гомеля до Москвы. Если смотреть цену билета на поезд, то сейчас купе обойдется ~90USD, плацкарт -- ~45USD. В одну сторону. Если брать билеты и туда, и обратно, то ~180USD в купе или ~90USD в платцкартном вагоне. Пара-тройка поездок в месяц за свой счет и транспортные расходы становятся слишком ощутимыми, что бы их игнорировать. Хотя, если мотаешься за счет заказчика -- это не так критично (тем не менее, собственные издержки всегда хочется минимизировать).

Понятное дело, у железной дороги появились конкуренты в виде автобусов и маршруток. Сейчас у нас в городе есть, как минимум, семь автотранспортных компаний, которые возят пассажиров в Москву на автобусах и микроавтобусах. Цены у всех одинаковые -- чуть больше $20. Т.е. билеты туда-обратно на маршрутку обойдутся дешевле, чем один плацкарт в одну сторону.

Конечно же, уровень удобства и комфорта у автоперевозчиков не сравнить с таковым у железнодорожников. Путешествие на маршрутке/автобусе в Москву -- это то еще удовольствие, 9-10 часов в кресле и возможность воспользоваться туалетом только на автозаправочных станциях можно считать весьма серьезным испытанием. Особенно в холодное время года. Тем не менее, как мне показалось, недостатка в пассажирах автоперевозчики не испытывают и ежедневно отправляют из Гомеля в Москву и обратно где-то по 150 человек.

Однако, что больше всего доставляет в этой ситуации, так это впечатление, что белорусская чугунка вообще не видит никакой проблемы. Ну теряют они по три плацкартных вагонов ежедневно. Ну и фиг с ним. Чем установить цену плацарты максимум в $30, лучше тупо сократить количество вагонов. Если лет десять назад в Москву в 55-ом поезде было порядка пяти купейных вагонов и с десяток плацкартных, то сейчас купейных всего два + штук пять плацкартных. Плюс к тому 75-й поезд стал ходить не каждый день.

Такое ощущение, что руководство железной дороги решило компенсировать затраты на пассажирские перевозки уменьшением количества мест при серьезном увеличении стоимости билетов. Может они полагают, что это выгоднее, чем большое количество дешевых мест. Но интересно было бы увидеть какое-то экономическое обоснование такого решения. При том, что внутри РБ цены на поезда ну очень демократичные, если сравнивать с международными линиями (например, купе на поезд Гомель-Гродно обойдется ~10USD, а по расстоянию это почти как от Гомеля до Москвы).

PS. Намедни обнаружил еще интересное. Если ехать из Гомеля в Минск, а затем лететь из Минска в Москву на самолете, то на некоторых рейсах суммарная стоимость всего этого дела (т.е. Гомель-Минск-Аэропорт-Москва) обойдется даже дешевле, чем купе Гомель-Москва. И времени потребуется гораздо меньше: выезжаешь из Гомеля в 7:00, в 15:00 уже в Москве (во Внуково).

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

[prog.flame] Теплая ламповая сишечка, говорили они...

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

int 
ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta)
{
   char* dup = strdup(ta);
   if(!dup) return UB_NOMEM;
   lock_basic_lock(&ctx->cfglock);
   if(ctx->finalized) {
      lock_basic_unlock(&ctx->cfglock);
      free(dup);
      return UB_AFTERFINAL;
   }
   if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
      lock_basic_unlock(&ctx->cfglock);
      free(dup);
      return UB_NOMEM;
   }
   lock_basic_unlock(&ctx->cfglock);
   return UB_NOERROR;
}

Классно, не правда ли? Прилежанию автора можно только позавидовать.

А потом настучать по рукам. За то, что не использует хотя бы идиому goto cleanup. Если уж перейти на C++ ума не хватило.

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

воскресенье, 11 сентября 2016 г.

[life.photo] Впечатления от Fujifilm x30 после года работы с ним

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