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

О блоге

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

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

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

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

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

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

среда, 22 мая 2024 г.

[prog.c++.fantasy] Даешь по два стандарта в год!

Отдельная боль для меня в последние годы -- это возврат C++ к ситуации, которая была с первым стандартом в конце 1990-х: стандарт вышел, а компиляторов, которые бы его поддерживали, пришлось ждать несколько лет. А пока этого не случилось приходилось оглядываться на то, что есть в конкретном компиляторе.

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

Однако, C++20 вернул нас в старые и недобрые времена. Уже середина 2024-го года, а полностью и нормально C++20 вроде как нигде и не реализован.

Что в этом плохого лично для меня?

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

Это все время. Чем дольше приходится ждать поддержки очередного стандарта, тем больше уходит этого самого времени 🙁

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

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

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

Не, реально.

Вот есть N предложений в работе. Какая-то часть из уже готова к включению в стандарт и просто ждет, пока же придет время фиксации этого стандарта. Так зачем ждать год-полтора-два, если уже есть готовые предложения? Давайте фиксировать по два стандарта в год. Например, весной -- C++24.1, осенью -- C++24.2. На следующий год весной будет C++25.1, а затем, осенью 2025-го, C++25.2 и т.д.

Как по мне, так хуже не станет.

Большие фичи, вроде модулей из C++20, могут (и будут) реализовываться годами. В 2024-ом году для меня нет разницы не реализованы ли модули из C++20 или же из C++23.2. Все равно же не реализованы.

Зато какая-нибудь мелкая фича, типа std::start_lifetime_as могла бы стать доступной для разработчиков в гипотетическом C++22.1, а не в С++23. Или вот в C++26 обещают добавить возможность обращаться к элементам parameter pack прямо по индексу. Так зачем ждать C++26, если можно включить ее в C++24.2?

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

Да, комитет по развитию C++ нужен. Спецификации языка, выпускаемые этим комитетом, нужны.

Но вот нужен ли на этих самых спецификациях штамп "ISO"? Сильно сомневаюсь. Возможно, в 1990-е развитие в рамках ISO имело смысл. Сейчас же его сложно разглядеть. А посему можно и задаться вопросом: а стоит ли сейчас цепляться за существующую модель стандартизации C++ или же выгоднее ее пересмотреть?

понедельник, 20 мая 2024 г.

[prog.c++] Первые краткие впечатления от C++20

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

spaceship operator. "Дайте два!" После того, как попробуешь, просто не хочется возвращаться на C++17.

designated initializers. Отличная штука для простых структур с двумя-тремя полями.

std::span "изкаропки". Очень удобно.

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

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

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

class class_with_complex_logic {
  concept MyRequirement = ...;

  template<MyRequirement Param>
  void do_something(Param && param) {...}

  template<MyRequirement Param>
  void do_something_else(Param && param) {...}
  ...
};

суббота, 11 мая 2024 г.

[prog.c++] Из непонятого: как же лучше погружать в современный C++ новых людей?

У меня недавно закончился небольшой контракт на проведение для молодых программистов чего-то вроде "курса молодого бойца" по C++. Что заставило в очередной раз задуматься на тему "а не стал ли C++ настольно монстрообразным, что обучить новичка практически невозможно?"

Но это сильно глобальный вопрос, я даже не знаю как к нему подойти. Радует лишь то, что сам я C++ изучаю года с 1991-го, когда это был, мягко говоря, совсем другой язык. Гораздо более простой, последовательный и логичный. И мне повезло, что на эту небольшую базу затем инкрементально ложились новые возможности: пространства имен, исключения, шаблоны, STL и т.д., и т.п. Т.е. сам я учил C++ по мере того, как в него добавлялись новые фичи. И поскольку добавлялись они раньше не в таком количестве и не с такой скоростью, то поспевать за ростом сложности C++ где-то до 17-го стандарта еще удавалось. Однако, на C++20 это уже сломалось даже для меня :(

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

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

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

Как по мне, Си и C++ уже очень и очень давно совершенно разные языки. Да, в C++ есть изрядное подмножество чистого Си, но все-таки идеология C++ другая и к таким вещам, как ссылки, классы, деструкторы, нужно привыкать сразу. Чем меньше приемов из чистого Си, тем лучше.

Поэтому вроде как есть смысл новичков сразу учить использовать то хорошее, что есть в C++. Например, std::string для строк вместо char*, std::string_view вместо const char*, std::vector и std::array вместо Си-шных массивов, std::find_if вместо голых циклов и вот это вот все.

Но тут есть серьезная засада, особенно в случаях, когда у новичков за плечами уже есть опыт работы с языками со сборкой мусора (будь то Python или Java, не суть важно). По моим впечатлениям у тех, кто изучает C++ сейчас, есть проблемы с пониманием разницы между values и references. Грубо говоря, люди пишут:

void f(std::string param) {...}

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

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

Как следствие, та же move-семантка, без которой современный C++ был бы не нужен в принципе, не очень хорошо заходит. Научить избегать копирования -- это уже задача. А научиться избегать копирования за счет грамотного и регулярного использования move-семантики оказывается задачкой со звездочкой.

Рефлексируя на эту тему я пока придерживаюсь мнения, что виной тому как раз использование готовых "высокоуровневых" возможностей STL. Те же самые std::string и std::vector освобождают программиста от изрядного геморроя, но не дают этому самому программисту понимания того, как же это все работает "под капотом". А без такого понимания сложно программировать на C++ эффективно.

Что заставляет задуматься о том, чтобы учить людей C++у без использования готовых классов и шаблонов из STL.

Грубо говоря, если начинать обучение с того, чтобы молодой C++ник сам написал аналог string-а, vector-а и hash_map-а, сам бы почувствовал где и когда вызываются конструкторы, деструкторы, операторы копирования, где требуется выделить память, где освободить, где скопировать содержимое и столкнуться с проблемой exception safety... Вот если начинать обучение с этого, то может быть у человека будет гораздо больше понимания разницы между передачей по значению или по ссылке, между копированием и перемещением и т.д., и т.п.

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

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

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

В-третьих, этот подход как раз таки очень близок к подходу, когда мы сперва учим людей чистому Си, а уже затем переходим к использованию высокоуровневых возможностей C++. Близок, не не тождественен. Тем не менее, если молодой разработчик привыкает писать относительно низкоуровневый код с ручными new/delete, alignof/alignas и пр. заморочками, то есть опасность, что он и продолжит в том же духе. Тут людей сразу пытаешься учить пользоваться std::unique_ptr и std::make_unique, а они все равно норовят использовать голые владеющие указатели с new/delete... Что уж говорить о тех, кого специально с самого начала ограждают от std::unique_ptr, std::optional, std::variant, std::vector и т.д.

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

В завершение еще раз поделюсь своими тягостными впечатлениями о том, что C++ на мой взгляд, стал слишком уж большим и сложным для того, чтобы его мог изучить и освоить человек "со стороны". Речь не о старпёрах, вроде меня, кто за 30 лет в программизме имел возможность осваивать фичи "современного C++" по мере их появления. А о тех, кто про C++ ничего не знал, но должен изучить за относительно небольшое время. Как таким новичкам преподавать тот же С++20? Вот это вопрос.

Хотя, может быть я излишне пессимистичен. Может это лично мне тяжело осваивать C++20, т.к. я уже старый, мозги уже плесневеть начали, много там лишних и устаревших знаний скопилось, да еще и не так уж много возможностей применять C++20 на практике. Отсюда и мое собственное заблуждение о том, что изучать C++20 сложно. А когда человеку 20 лет, все вокруг неизвестно и удивительно, то может быть C++20 залетает в пустую юную голову просто "на ура"... Ведь может же быть и такое.

четверг, 2 мая 2024 г.

[prog.c++] Одно из недооцененных мной качеств C++

Есть в C++ одно качество, на которое я сам начал обращать внимание относительно недавно, года три или четыре назад. А вот поговорить об этом захотелось только сейчас, после выхода большой статьи "Leaving Rust gamedev after 3 years" (ее перевод уже начали делать и на Хабре -- вот первая часть).

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

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

Читая эту "претензию" к Rust-у вспомнил про то самое качество C++ о котором и пойдет сегодня речь.

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

Да, да. Речь именно о том, что на C++ любой "недоучка" может написать работающий говнокод. Ключевое здесь "работающий", а "говнокод" -- это так, функция от времени ;)

И, что еще интереснее, даже работающий с приемлемой скоростью.

Т.е. неопытный C++ник из говна и палок может получить нужное ему решение.

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

Но здесь и сейчас он будет работать.

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

Грубо говоря, два-три человека, не сведущих в C++, берут и пишут несколько тысяч (а то и несколько десятков тысяч) строк кода на C++, в итоге получается первая версия работающего продукта, которая и позволяет продукту начать свой путь к потребителю. А это, по большому счету, и есть самое главное.

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

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

Выше я не зря взял термин "недоучка" в кавычки. Иногда это студенты, которые слишком рано, не имея практического опыта, попали "под крыло" к специалистам в какой-то узкой прикладной нише. Иногда это люди, которые уже умеют программировать и, зачастую, делают это очень хорошо. Но не на C++, а на Python-е или VisualBasic-е, к примеру. Да и вообще в своей предметной области съели не одну собаку. И, что самое важное, они знают что нужно клиентам и как это клиентам продать.

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

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

Так-то я привык к работе в условиях, когда качеству уделяется серьезное внимание, и думал, что подход "фигаг-фигак-и-в-продакшен" за последние 15-20 лет из C++ полностью ушел в Java, Python и Go. Просто в силу того, что ниша C++ все эти годы скукоживается и C++, к счастью, остается лишь там, где в этом еще есть смысл.

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

Почему не ведет к фатальным последствиям для меня пока еще загадка. Могу предположить, что здесь здорово помогают современные средства разработки с крутыми отладчиками, анализаторами и санитайзерами. Ну и стандартная библиотека C++, хоть и остается куцей, но хотя бы std::vector и std::string уже есть везде, не нужно свое колхозить, как было в 1990-х.

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


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

Но если над кодовой базой должно работать несколько десятков человек с разной квалификацией, то C++ плохой выбор (жирное ИМХО).

среда, 1 мая 2024 г.

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

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

Фильмы

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

Хитмен. Последнее дело (Knox Goes Away, 2023). Отличная развязка. Но чтобы ее дождаться придется вытерпеть полтора часа скучной тягомотины.

Манкимэн (Monkey Man, 2024). Ну что тут сказать? Можно вывезти индуса в Голливуд, но вывести Болливуд из индуса невозможно. Как по мне, так даже попытки сделать экшОн в духе "Джона Уика" не помогают.

Сериалы

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

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

Банда «ЗИГ ЗАГ» (первый сезон, 2023). Динамично. Нет ни грамма сериальной затянутости. Но столько клюквы развешено, что как-то не по себе местами становится.

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