воскресенье, 30 декабря 2018 г.

Отчет о CPPCON 2018 (часть 2)

1. Fast Conversion From UTF-8 with C++, DFAs, and SSE Intrinsics


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

2. Spectre: Secrets, Side-Channels, Sandboxes, and Security


Интересно для общего развития.

3. A Little Order: Delving into the STL sorting algorithms


Короткий 20-минутный доклад. Можно посмотреть, чтобы освежить в памяти использование таких алгоритмов STL как std::sort, std::partial_sort, std::stable_sort, std::nth_element.

4. State Machines Battlefield - Naive vs STL vs Boost


Выступающий пытался реализовать простую стейт машину с использованием таких средств как std::variant, boost::statechart, boost::msm, coroutines (co_await, co_return), которые будут доступны в С++ 20. В рассказе были обозначены преимущества и недостатки того или иного подхода. В целом доклад получился познавательным, хотя конечно не стоит от него ждать просветления.

5. 105 STL Algorithms in Less Than an Hour


Джонатан Бокара уже не первый год ездит по миру, выступая в различных конференциях со своим докладом про STL алгоритмы. В этом году он уже выступал с этим докладам у нас на конференции (ссылка https://www.youtube.com/watch?v=tO_drboJfxs) CPP Russia, которая проходила в Питере. Кроме того Джонатан ведет довольно занятный блог (https://www.fluentcpp.com) с большим количеством интересных статей по С++, обобщенному программированию, и, разумеется, STL. Его доклады имеет смысл смотреть преимущественно для фана при наличии свободного времени, в основном с целью освежить в голове какие-то знания, которые и так в принципе все знали, но возможно забыли из-за того, что не применяли на практике в последнее время.

воскресенье, 25 ноября 2018 г.

Конференция dotnext 2018 - отчет

В этом году мне удалось побывать на конференции Dotnext 2018 для .Net разработчиков, которая проводилась в Москве 22-23 ноября. Мероприятие проходило на территории гостиницы Украина на Кутузовском проспекте и была организована по высшему разряду с питанием, кофебрейками, ништяками и прочим.



На конференцию были приглашены такие известные личности как Джефри Рихтер, Павел Йосифович и др.



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

Доклад Джефри Рихтера - Generics

Маэстро рассказывал про дженерики в .Net. Уровень материала - разжевывание дженериков студентам второго курса для подготовки к сдаче лабы.
Однако, одна прозвучавшая мысль меня порадовала. Рихтер рассказал, чем отличаются шаблоны в .Net framework от шаблонов в C++. Я и раньше мог на пальцах объяснить, в чем отличие, но не хватало общего понимания картины. Теперь же пазл сложился :) Основная и главная особенность дженериков в .Net состоит в том, что в .Net дженерики остаются дженериками после компиляции в байт код :) Всё, точка. Этого ответа достаточно на вопрос, в чем различия между дженериками в плюсах и в дотнете. Всё остальное просто следствия это факта.

Доклад Джефри Рихтера - Building responsive and scalable applications

Джефри, как и на первом своем докладе про дженерики, просто перечитывал на память главы из своей книги. Уровень сложности материала можно оценить как для начинающих.
При каждом переключении контекстов потоков Windows выполняет следующие операции:
1. Сохранение регистров текущего потока в оперативной памяти
2. Вычисление того, какой поток должен выполняться следующим.
3. Загрузка данных нового потока в регистры процессора.
4. Переключение контекстов может приводить к промахам при поиске по кешам процессора.
Всё это приводит к деградации производительности.
Вывод: используйте потоки, как можно реже. Для работы с диском, сетью и др. следует использовать асинхронное API.

Системные метрики: собираем подводные камни

Доклад про то, как программно получать и логировать какие-нибудь интересные метрики. Для этого есть следующие доступные варианты:
1. Получение performance counters через стандартные .Net методы из пространства имен System.Diagnostics. Надо иметь в виду, что категория Process весьма медленная.
2. Еще один способ сбора метрик - это использование функции RegQueryValueEx(HKEY_PERFORMANCE_DATA, "230 784", ...). Всегда лучше сравнивать разные способы сбора метрик.
3. Performance Data Helpers (pdh.dll). Имеет смысл использовать PDH, если уперлись в ограничения .Net обертки.
4. ETW - event tracing for Windows. Записывает евенты от различных провайдеров: .Net CLR provier, Kernel-Network provider, custom provider.
Также докладчик приводил интересные примеры из собственной практики, с какими проблемами ему приходилось сталкиваться при сборке метрик, и как он их решал.
Хороший блог Bruce Dawson, в котором много интересных статей на тему вопросов performance в Windows.
Рекомендую этот доклад к просмотру!

Создание окружения для интеграционных тестов на основе Docker-контейнеров

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

Windows 10 internals for .NET developers Pavel Yosifovich

1. Для лучшего понимания положения .Net в операционной системе Windows показал всю цепочку вызовов функций при обращении к методу File.Read(), начиная с библиотеки типов .Net и заканчивая HAL.
2. Рассказывал про jobs: как их создавать, как использовать с примерами.
3. Приоритеты потоков
4. Processor Affinity. Это про то, на каком процессоре должен выполняться тот или иной поток, и как этим можно управлять.
5. Waitable kernel objects: семафоры, мьютексы, евенты.
К сожалению, ничего нового не узнал.

Yield и async-await: как оно все устроено внутри и как этим воспользоваться

Также хочется отметить этот доклад. В этом докладе докладчик рассказал про ICFP Contest - соревнование для программистов. И показал на примере решения одной из задач с этого соревнования, каким образом можно применять конструкции yield return и async await. В ходе рассказал было подобно описано, как эти конструкции устроены внутри, как выглядит byte код для них, и как они работают.
Из этого доклада вряд ли можно будет получить много полезной информации с точки зрения практического применения. Однако, содержимое доклада и подача материала докладчиком показались мне весьма увлекательными. В итоге, посмотрел доклад с удовольствием.
Рекомендую этот доклад к просмотру!

От монолита к микросервисам: история и практика

1. С преимуществами микросервисной архитектуры всё понятно:
- Модульность. Все компоненты системы разделены на модули, которые можно разрабатывать, поддерживать и деплоить независимо от остальных.
- Проще разделить зону ответственности между разработчиками.
- Высокая отказоустойчивость.
- Разнообразие технологий.
2. Все микросервисы должны быть логически независимыми функциональными единицами, которые общаются через какую-то общую шину данных. Если у вас один микросервис обращается к другому, а то к третьему, то это антипаттерн.
3. Для управление контейнерами хорошо бы использовать какую-нибудь систему оркестрации, например, Kubrnetes.
4. Грамотно настроенная система мониторинга микросервисов может сильно облегчить жизнь.
5. При переходе от монолита к микросервисам не обязательно сразу начинать всё ломать и крушить. Можно постепенно по мере готовности микросервисов отрезать те или иные куски монолита, переключая систему на использование публичного API микросервисов.
6. Сложнее всего разделять базу данных.
Полезные ссылки:
Мартин Фаулер про микросервисы.
Хорошая статья про микросервисы на хабре.

Domain-driven design: рецепт для прагматика

Основные принципы DDD:
1. Общий язык, используемый в терминологии, между всеми участниками проекта: начиная с разработчиков, закачивая бизнесом.
2. Контекст доменной модели. Все бизнес сущности, используемые при проектировании системы, должны не выходить за рамки принятого контест доменной модели. Модели должны быть ограничены своими контекстами.
3. Больше общения между девеломентом и бизнесом.
4. Максимально выразительный код интерфейсов бизнес логики.
Хорошая статья на хабре про проектирование и архитектуру - Как мы попробовали DDD, CQRS и Event Sourcing и какие выводы сделали.

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

Отчет о CPPCON 2018 (часть 1)

В сентябре завершилась одна из самых крупных конференций для C++ разработчиков cppcon 2018. На этот раз она проходила в Бельвью. В ней приняли учасие такие гуру своего дела как Андрей Александреску, Скот Мейерс, Бьёрн Страуструп, Герб Саттер и другие, чьи имена у всех на слуху, и книги которых многие конечно читали.
Из того, что показалось интересным мне, я бы выделил следующие выступления:

1. Louis Dionne "Compile-time programming and reflection in C++20 and beyond" 


Доклад получился познавательным и интересным. Louis Dionne периодически участвует в разного рода конференциях, выступая преимущественно с докладами по шаблонам, метапрограммированию в С++, Boost.Hana и другим связанным темам, делая при этом всегда упор на новые стандарты С++.
Автор много рассказывал про constexpr, про развитие возможностей, который предоставляет этот инструмент в разных редакциях стандарта. Всё идет к тому, чтобы постепенно увеличивать и наращивать доступные программисту средства языка, которые можно использовать в купе с constexpr. Так, например, в C++ 17 возможность использования if constexpr позволяет целиком заменить некоторые сложные блоки SFINAE. Таким образом в связи с перспективами дальнейшего развития constexpr, его следует активно использовать там, где это необходимо.
Также автор рассказывал про рефлексию типов, которая будет доступна в будущих стандартах языка. Концепция рефлексии в С++ очень напоминает рефлексию в .Net, которая доступна всем C# девелоперам с ранних версий .Net. К примеру, можно будет написать универсальный метод вывода в поток названия элемента любого енума.

2. Kate Gregory "Simplicity: Not Just For Beginners"


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

3. Bjarne Stroustrup "Concepts: The Future of Generic Programming (the future is here)"


Здесь Страуструп больше часа рассказывал про концепты, которые нас ожидают в С++ 20. На мой взгляд доклад можно было бы сделать хотя бы раза в полтора короче. Но в целом посмотреть однозначно стоит. Концепты уже точно появятся в С++ 20, и судя по тому, как видит развитие языка его создатель, у концептов большое будущее. Поэтому вполне логично инвестировать свое время в изучении данного средства языка уже сейчас с тем, чтобы применять его по возможности на практике в дальнейшем.
Из примера на вики концепты могут быть объявлены как-то так:
template <class T>
concept bool EqualityComparable() {
    return requires(T a, T b) {
        {a == b} -> Boolean; // Boolean is the concept defining a type usable in boolean context
        {a != b} -> Boolean;
    };
}
С одной стороны это просто дополнительное ограничение для шаблонного параметра. То же самое можно было бы получить с использованием std::enable_if и SFINAE. Но с другой использование концептов делает код гораздо более читаемым и лаконичным.
Кроме того, как обещает Страуструп, использование концептов значительно сократит время компиляции по сравнению с использованием стандартных средств обобщенного программирования.

Читайте продолжение отчета во второй части. 

пятница, 7 сентября 2018 г.

Перегрузка и частичная специализация функций

Возьмем следующий пример кода:
template <typename T> void foo(T); // строка 1
template <typename T> void foo(T*); // строка 2
template <>           void foo<int>(int*); // строка 3
Здесь в строке 1 мы объявляем шаблон функции с одним параметром T.
В строке 2 перегружаем нашу шаблонную функцию.
В строке 3 выполняем полную специализацию шаблонной функции, а именно ее перегруженного варианта в строке 2.

Теперь попробуем переставить строки 2 и 3 местами:
template <typename T> void foo(T); // строка 1
template <>           void foo<int*>(int*); // строка 2
template <typename T> void foo(T*); // строка 3
В обоих случаях будем вызывать нашу функцию так:
foo(new int);
Вопреки ожиданиям столь незначительное изменение меняет поведение программы.
Дело в том, что теперь специализация шаблонной функции в строке 2 относится к шаблонной функции в строке 1.

Далее в игру вступает та особенность компилятора, при которой он сначала выбирает наиболее подходящую перегрузку функции, а затем для данной перегрузки еще выбирает специализацию.
В первом фрагменте кода, компилятор сначала выбирает подходящую перегрузку функции, что для new int очевидно соответствует строке 2, а затем выбирает подходящую специализацию, и в итоге вызывается функция из строки 3:
template <>           void foo<int>(int*); // строка 3
Во втором фрагменте кода, компилятор всё также сначала выбирает перегрузку функции, это строка 3, потом смотрит, если ли специализации, но специализаций у данной функции нет. Во втором фрагменте кода специализация есть только у функции из строки 1, а у функции из строки 3 нет. В итоге вызывается функция из строки 3:
template <typename T> void foo(T*); // строка 3
По это причине не рекомендуется одновременно использовать перегрузки функций и их полную специализацию.

Куда сходить в Москве на выходных

Зеленым отметил, где уже был.
Желтым то, что хотелось бы посетить следующим.

суббота, 3 февраля 2018 г.

Способы вызвать крах программы в С++

Следующие способы вызвать крах программы в C++ взяты из книги Саттера.
  1. memset(0,1,1) - обращение по нулевому указателю
  2. abort()
  3. static_cast<char*>(0) = 0 - обращение по нулевому указателю
  4. static_cast<void(*)()>(0)() - вызов несуществующей функции по нулевому указателю
  5. throw std::logic_error()
  6. throw 0