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

[prog.c++] Статистика по использованию try-catch в исходниках SO-5.5.18

На волне темы про использование исключений подсчитал, как часто в исходниках последней стабильной версии SO-5.5.18 встречаются блоки try-catch. Общий объем ядра SO-5 порядка 25KLOC (не считая пустых строк и комментариев). Всего насчитал 25 блоков try (в двух-трех блоках по 2 секции catch). Из общего числа catch-ей:

  • в 10 случаях catch используется для преобразования одного типа исключения в другое. В нескольких из этих случаев перед пробросом нового исключения выполняются действия по очистке/откату операций;
  • в 7 случаях в catch-е иницируется вызов std::abort() (перед этом зачастую идет логирование проблемы);
  • в 4-х случаях исключение "проглатывается". В двух из них предварительно логируется;
  • в 3-х случаях ловятся исключения, выпущенные из обработчиков событий агентов. В этих catch-ах происходит то, что описывалось в свежей статье на Хабре;
  • в одном случае ловится исключение, выпущенное из обработчика события агента, для фиксации этого исключения в std::promise. Этот сценарий используется для синхронного взаимодействия агентов;
  • в одном случае используется логика на исключениях: с помощью исключения разрывается цикл выборки событий из очереди одного из диспетчеров. Оказалось, что такая реализация цикла самая простая;
  • и в одном случае catch используется для эмуляции noexcept для старых VC++ компиляторов.

В общем, получается где-то по одному try-catch на тысячу строк кода.

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

А вот два других случая с игнорированием исключений интереснее. Один из них такой (сорри за качество английского):

   //! Switching storage from map to vector.
   void
   switch_storage_to_vector()
      {
         // All exceptions will be ignored.
         // It is because an exception can be thrown on staged 1-2-3,
         // but not on stage 4.
         try
            {
               // Stage 1. New containers to swap values with old containers.
               // An exception could be thrown in the constructors.
               map_type empty_map;
               vector_type new_storage;

               // Stage 2. Preallocate necessary space in the new vector.
               // An exception can be thrown here.
               new_storage.reserve( m_map.size() );

               // Stage 3. Copy items from old map to the new vector.
               // We do not expect exceptions here at v.5.5.12, but
               // the situation can change in the future versions.

               // Use the fact that items in map is already ordered.
               std::for_each( m_map.begin(), m_map.end(),
                  [&new_storage]( const map_type::value_type & info ) {
                     new_storage.push_back( info.second );
                  } );

               // Stage 4. Swapping.
               // No exceptions expected here.
               m_vector.swap( new_storage );
               m_map.swap( empty_map );
               m_storage = storage_type::vector;
            }
         catch(...)
            {}
      }

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

Какова мораль? Да нет никакой морали. Просто любопытно стало. Думаю, что для библиотек небольшое количество try-catch -- это нормально. В прикладном кода плотность испрользования try-catch наверняка выше.

пятница, 7 октября 2016 г.

[prog.flame] Длина строки кода таки важная штука

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

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

Еще раз убедился в том, что ограничение на 78-80 символов для длины строки кода -- это вполне разумно.

PS. Длинная строка -- это когда 100+ символов.

вторник, 4 октября 2016 г.

[prog.c++] Официальный анонс конференции Corehard C++ Autumn 2016 в Минске

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


Добрый день, друзья!
22 октября сообщество CoreHard.by проведет очередную большую конференцию выходного дня, посвященную языку С++ и сопутствующим «хардкорным» технологиям. Спикеры из ведущих IT-компаний Беларуси, России и не только соберутся вместе, чтобы рассказать о своем опыте в разработке и тестировании. Мы собрали лучшие доклады на самые различные темы: модели акторов и бинарная совместимость, эффективная работа с JSON в С++, рефлексия для С++ и GMock framework, рассказы непосредственных участников о разработке Bing и PVS-Studio для Linux и многое-многое другое.
Приглашенные спикеры:
  • Антон Полухин (Яндекс, Москва) – активный разработчик C++ библиотек Boost, автор книги “Boost C++ Application Development Cookbook” и представитель в международном комитете по стандартизации С++ от России. Антон расскажет о том, как организовать рефлексию в C++14 на этапе компиляции без макросов и вспомогательной разметки.
  • Егор Кишилов (Microsoft, Редмонд, США) более 8 лет работает в Microsoft, все это время занимаясь разработкой поисковой системы Bing. Егор расскажет о том, как построена разработка в Microsoft и что из себя представляет поисковая система Bing.
  • Святослав Размыслов (PVS-Studio, Тула, Россия) руководит отделом, занимающимся разработкой ядра анализатора PVS-Studio для анализа C и C++ кода. Святослав расскажет о том, как создавалась версия PVS-Studio под Linux.
  • Евгений Охотников – независимый разработчик с более чем 20-летним стажем, занимается OpenSource-инструментарием для упрощения разработки многопоточных приложений на языке C++. Евгений расскажет о моделях акторов для С++.
Полную сетку докладов ищите на нашем официальном сайте.
Конференция состоится в субботу, 22 октября и будет проходить в два потока.
Совместно с компанией JetBrains мы проведем розыгрыш лицензий на продукты ReSharper C++, CLion, AppCode среди участников.
Друзья, регистрация обязательна, спешите зарегистрироваться наофициальном сайте конференции.
Приходите, будет интересно!
С уважением,
Команда CoreHard.by

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

[prog.c++] Вопрос за двоичную сериализацию в С++

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

Что вы использовали в этих случаях?

Какой-то готовый инструмент, вроде asn1-компилятора, protobuf, thrift, cap'n'proto, cereal, boost::serialization или что-то другое? Писали все сами?

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


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

Буду признателен как за ответы на эти вопросы, так и на распространение ссылок на этот пост.

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

[prog.flame] portfile.cmake из Vcpkg супротив рецепта для MxxRu::externals

Попробовал представить, как сделать адаптацию SO-5 под новую волшебную пилюлю от Microsoft под названием Vcpkg. Проблевался. Какую только херню, пардон май френч, народ готов жрать только потому, что эта херня от MS или от Google. Поразительно.

Суть Vcpkg в том, что под каждый проект, который хочется затянуть в этот самый Vcpkg, нужно создать файлик portfile.cmake, в котором будут находится инструкции по доставанию исходников этого проекта и по его сборке (если проект нуждается в сборке). Для примера покажу, как выглядит portfile.cmake для библиотеки Range-V3. И как это же самое выглядит в виде рецепта для MxxRu::externals.

Итак, portfile.cmake для Vcpkg:

include(vcpkg_common_functions)
set(SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src/Range-V3-VS2015-ede9ad367fd5ec764fecb039c874614bd908e6b6)
vcpkg_download_distfile(ARCHIVE
    URLS "https://github.com/Microsoft/Range-V3-VS2015/archive/ede9ad367fd5ec764fecb039c874614bd908e6b6.zip"
    FILENAME "range-v3-ede9ad367fd5ec764fecb039c874614bd908e6b6.zip"
    SHA512 e978c7694471d8616c248647b77689f377b3e2517347abde8629b140e5994de8bf686565a24cdd7dd222f325d43b775f5e478c91220dce75313985499b134637
)
vcpkg_extract_source_archive(${ARCHIVE})

file(COPY ${SOURCE_PATH}/LICENSE.txt DESTINATION ${CURRENT_PACKAGES_DIR}/share/range-v3)
file(RENAME ${CURRENT_PACKAGES_DIR}/share/range-v3/LICENSE.txt ${CURRENT_PACKAGES_DIR}/share/range-v3/copyright)
file(INSTALL ${SOURCE_PATH}/include DESTINATION ${CURRENT_PACKAGES_DIR} FILES_MATCHING PATTERN "*.hpp")
vcpkg_copy_pdbs()

Тоже самое для MxxRu::externals:

MxxRu::arch_externals :range_v3_vs2015 do |e|
  e.url 'https://github.com/Microsoft/Range-V3-VS2015/archive/ede9ad367fd5ec764fecb039c874614bd908e6b6.zip'
  e.sha512 'e978c7694471d8616c248647b77689f377b3e2517347abde8629b140e5994de8bf686565a24cdd7dd222f325d43b775f5e478c91220dce75313985499b134637'

  e.map_dir 'include/*' => 'dev/range-v3'
  e.map_file 'LICENSE.txt' => 'dev/range-v3/*'
end

Резюмируя. Если кому-то действительно нужно, чтобы SO-5 был доступен из портов Vcpkg, то дайте знать. Мы сделаем. Но только если это кому-то действительно нужно. Ибо Vcpkg выглядит как говно и пахнет как говно. А посему вмазываться в говно и сопровождать потом это говно просто так не хочется, только если на то будут причины.

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

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

Любой ценой (Hell or High Water, 2016). Понравилось, посмотрел с большим удовольствием.

Мистериум. Тьма в бутылке (Flaskepost fra P, 2016). Понравилось. Очень достойная серия криминальных фильмов получилась (если кто не видел, то советую начать с двух первых частей: Мистериум. Начало (Kvinden i buret, 2013) и Убийцы фазана (Fasandræberne, 2014), тогда будет лучше понятно, откуда взялись главные герои-следователи.

Торо (Toro, 2016). Неплохо. Европейцы все-таки снимают криминальные драмы как-то не так, как американцы.

Заклятие 2 (The Conjuring 2, 2016). Если первое "Заклятие" понравилось, то нужно смотреть и второе. Как по мне, так достойное продолжение.

Джейсон Борн (Jason Bourne, 2016). Ждал от фильма сильно большего. Если бы не погоня на автомобилях в конце, так вообще бы разочаровался бы.

Великолепная семерка (The Magnificent Seven, 2016). Постреляли в фильме от души, но, что странно, ни за кого из героев переживать не хотелось. Так что фильм смотрится просто как тщательно сделанный аттракцион с весьма предсказуемым финалом.

Транс-Пекос (Transpecos, 2016). Если бы не излишняя затянутость, то могла бы получиться вполне добротная криминальная драма.

Поезд в Пусан (Busanhaeng, 2016). Корейское кино про зомби. Причем, про весьма шустрых и злобных зомби. Если корейское кино нравится, то можно смотреть. Хотя бы для того, чтобы увидеть, как корейцы к этой теме подходят.

Такой же предатель, как и мы (Our Kind of Traitor, 2016). Несмотря на наличие хороших актеров какого-то хорошего впечатления фильм на меня не произвел.

Отмель (The Shallows, 2016). Так себе. Финал вообще сказочный.

Безбашенный Ник (Tschiller: Off Duty, 2016). Редкая муть. Доставил разве что фрагмент с проездом на комбайне по центральным улицам Москвы под "Нас не догонят".

Спарта (2016). Не понял ни что это было, ни зачем я это смотрел. Но хотя бы сцены поединков были сняты более-менее нормально.

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

[prog.thoughts] Эпоха бородатых проектов уже наступила?

Программирование сейчас -- это слишком уж сегментированная область, чтобы говорить о программировании вообще. В каком-нибудь фронтэнде, где все меняется с калейдоскопической быстротой, наверняка дела обстоят совсем не так, как в мире хардкорного эбедеда для специализированных компьютеров с 16K RAM на борту. Однако, если брать ниши таких языков программирования, как C, С++, Java, C# и, может быть, даже Haskell/OCaml/Scala, то в этих нишах библиотеки с историей развития в 10+ лет уже не редкость. Ну, например, Boost в C++ или Hibernate в Java -- это же самое начало 2000-х.

Причем Boost -- это чрезвычайно любопытный пример. Т.к. Boost, появившись более 15 лет назад, позиционировал себя как площадка для новых C++ных библиотек, специально созданных для современного C++ и которые двигают C++ вперед. Т.е. даже понятию "современный C++" уже очень прилично лет. Посему даже библиотеки, которые сразу стартовали с "современного C++", на данный момент уже имеют "лохматую историю" (см., например, Crypto++ и Botan). Что уж говорить про те библиотеки, которые появились на свет еще до стандартизации C++ (MFC, Qt, ACE).

Посему кажется, что мы уже живем в эпоху, когда нас окружают "бородатые" проекты с очень длительной историей развития. И с каждым годом это будет все более и более актуально. Пройдет лет пять-десять и, смешно сказать, 20-летние senior-разработчики и 25-летние solution-архитекторы будут собирать проекты из компонентов, которые будут постарше этих самых разработчиков и архитекторов :) А может где-то и сейчас уже так. Скажем, если речь идет об использовании СУБД Oracle или DB2.

PS. Но еще с большим интересом я лично жду времен, когда нынешняя братия молодых разработчиков постареет лет так на десять. Говорят, что сегодня средний возраст ИТ-шников у нас в РБ меньше 30 лет. Что, в принципе, понятно. Народ массово пошел в профессию где-то после 2004-го года, когда офшор в наших Палестинах стал всасывать все имеющиеся ресурсы как пылесос. Отсюда, полагаю, и засилье малолетних дебилов на профильных форумах. Тем интереснее станет, когда лет через 5-10 этот самый средний возраст существенно превзойдет 30 лет. Но это уже совсем другая история...