Результаты ежегодного опроса Annual C++ Developer Survey "Lite" за 2023 год наконец опубликованы, и мы можем почерпнуть из них ценную информацию об опыте C++ разработчиков. Одной из самых интересных целей этого опроса является выявление ряда болевых точек, с которыми приходится иметь дело C++ разработчикам.
В этой статье мы рассмотрим несколько узких мест в разработке на C++, на которые больше всего жаловались опрошенные разработчики.
Что из перечисленного вас больше всего раздражает в разработке на C++?
В этой категории было 16 вопросов. Респондентов попросили оценить серьезность каждой проблемы по шкале: “серьезная проблема” (major pain point), “небольшая проблема” (minor pain point) или “я не считаю это существенной проблемой” (not a significant issue for me).
Итак, три самых узких места по мнению опрошенных:
Управление библиотеками, от которых зависит мое приложение.
Время сборки.
Создание и настройка конвейера непрерывной интеграции с нуля (автоматизированные сборки, тесты и т. д.)
Также стоит отметить, что номером четыре в списке был пункт “Управление проектами CMake”, который, как мне кажется, связан с первыми пунктами.
Интересно, что для C++, широко известного (и критикуемого за это его пользователями) как большой и сложный язык, основные проблемы, похоже, связаны с инфраструктурой.
Одной из причин таких результатов, безусловно, является аудитория опроса. Более 50% опрошенных имеют опыт работы с С++ более 10 лет, а если считать тех, чей опыт работы превышает 5 лет, то мы и вовсе получим 80%. Так что для этой аудитории, я думаю, сам язык больше не является главной трудностью, поскольку эти пользователи научились с ним работать. А вот с инфраструктурой вокруг него до сих пор есть проблемы.
Давайте же разберем три самые неприятные болевые точки в порядке возрастания негодования пользователей языка.
№ 3: Создание и настройка конвейера непрерывной интеграции с нуля (автоматические сборки, тесты и т. д.)
Из примерно 1700 результатов 31.35% опрошенных считают это сильной головной болью, 40.85% — небольшой и 27,80% — несущественной.
Лично я удивлен, что этот пункт поднялся так высоко в рейтинге самых неприятных аспектов разработки.
GitHub или GitLab CI за последние несколько сделали очень много, чтобы помочь вам в развертывании ваших личных проектов. Если у вас нет проблем с зависимостями, о чем мы еще поговорим в следующих разделах, настройка конвейера CI/CD займет всего несколько минут после того, как вы освоите основы. Да, здесь есть некоторая кривая обучения, но с основами относительно легко разобраться. Это вполне реально сделать за полдня-день.
Касательно профессиональных проектов, я ожидаю, что настройкой CI/CD будет заниматься специально подготовленный человек или даже целая команда. Я полностью согласен с тем, что работа с такой организацией CI/CD или просто с другой командой может быть узким местом, и очень часто это именно так и есть. Но может быть тогда вопрос не об этом?
№ 2: Время сборки
Из примерно 1700 результатов 43.34% опрошенных считают это сильной головной болью, 37.56% — небольшой и 19.10% — несущественной.
Время сборки действительно может быть проблемой. Даже сразу по нескольким причинам. Проект может быть очень большим. Отсутствие управления зависимостями может вылиться в огромный монорепозиторий и кэширование не будет работать должным образом. Или же процессы сборки замедляют плохо настроенные антивирусные сканеры.
C++ пытается сгладить некоторые аспекты этой проблемы с помощью модулей в C++20. Также с ускорением процесса сборки могут помочь некоторые инструменты, например, ccache или distcc. Но для управления ими по хорошему необходимо выделять отдельного человека или целую команду. Еще больше помочь в преодолении этого узкого места могут инкрементальные сборки, так что проблема не так уж серьезна. За исключением того, что вам придется работать с одним заголовком, который все используют.
Но для развертываний, где вам желательно или даже необходимо собирать проекты с нуля, подготавливая сторонние библиотеки или создавая свою базовую систему Yocto, время сборки может быть реальной проблемой. И я предполагаю, что именно это подняло этот пункт так высоко.
№ 1: Управление библиотеками, от которых зависит мое приложение
Из примерно 1700 результатов 47.37% опрошенных считают это сильной головной болью, 35.09% — небольшой и 17.54% — несущественной.
Почти 50% респондентов считают управление зависимостями самой главной проблемой языка. Это много.
Управление зависимостями действительно представляет из себя проблему. Не все работают в Google, где бы вы могли сказать: а давайте не будем использовать OpenSSL и разработаем собственную криптобиблиотеку. Большинству проектов придется использовать то, что доступно.
Проблема начинается уже с систем сборки. Для библиотек C и C++ не существует стандартных систем сборки. Скорее всего, если вы используете 5 зависимостей, вам придется иметь дело с 3 разными системами сборки.
После того, как вы собрали зависимости, вам нужно выяснить, как сделать их доступными для проектов, в которых вы хотите их использовать. И обычно это нужно делать по-разному для разных платформ, целевых систем и, конечно же, для используемой системы сборки.
Если вы работаете на Windows и пишете под Windows, или на Linux и пишете под Linux (даже встроенный), вам может повезти, и вы найдете решение, которое идеально вам подойдет. И скорее всего именно так и происходит у людей, для которых этот пункт представляется небольшой или несущественной проблемой.
Но если вам нужно делать это для нескольких платформ, то это уже проблема совершенно другого масштаба. И здесь даже еще не идет речь о задаче отслеживания проблем безопасности в ваших зависимостях и реагировании на них.
И это еще не все: различные настройки компилятора, отладочные и релизные сборки, санитайзеры… на все это нужно тратить время и силы.
Компании очень часто упускают это из виду. Они хотят видеть реализованные фичи, а не тратить время на управление зависимостями. То, что фичи очень часто не могут быть реализованы без управления зависимостями, — это то, что приходит с практикой.
Существуют менеджеры зависимостей для C++, которые утверждают, что решили эту проблему. И для некоторых видов проектов они могут быть вполне пригодным решением. Но это не панацея. Они часто добавляют еще один уровень сложности и терпят неудачу в сложных сценариях, когда вы собираете проект под несколько платформ с несколькими компиляторами в разных конфигурациях и должны передавать решение нескольким командам, чтобы они могли дальше с ним работать.
Vcpkg и Conan прекрасно работают во многих сценариях, но имеют свои ограничения. Такие инструменты, как spak, зависят от платформы. Другие подходы, такие как CPM или FetchContent, превращают проекты в монорепозитории, создавая другие проблемы. И у нас есть системы сборки, такие как meson или xmake, которые поставляются со своими собственными решениями для управления зависимостями. Кроме того, каждая используемая вами зависимость может иметь собственное представление о том, как она управляет своими зависимостями и как она хочет быть собрана. И как только вы решите все это, если вам нужно работать под несколько команд с разными требованиями, инструментами и культурами, ты перед вами воссияет уже совершенно другой уровень этой проблемы.
Короче говоря, управление зависимостями может вылиться в полный беспорядок. И для некоторых проектов этот беспорядок может стоить слишком дорого.
Так что да, я считаю управление зависимостями в C++ основной проблемой на сегодняшний день. Таков был мой ответ в этом опросе. И, кажется, я не одинок в этой точке зрения.
Подытожим
Каждый из этих пунктов может быть отдельным постом в блоге, эссе или даже книгой. Можно много об этом говорить, но суть в том, что существует проблема с инфраструктурой C++.
C++ в том виде, в каком он есть сегодня, возможно, не сможет решить эту проблему. По крайней мере, не в таком контексте взаимодействия стандарт C++ с разработчиками, ISO/JTC1/SC22/WG21. Я могу кое-чего в этом не понимать, но я думаю, что если мы хотим решить проблему в контексте стандарта, нам, возможно, придется рассмотреть ISO/JTC1/SC7 с его рабочими группами или что-то подобное. Возможно, это можно было бы реализовать в связи с ISO/JTC1/SC7/WG4 (Tools and environment). Я не уверен что это когда-либо произойдет, но кто знает.
Я не думаю, что эта тема может быть решена вне стандарта. Решения вне стандарта привели нас к тому, что мы имеем сегодня – самой острой болевой точке.
Есть ли такие же проблемы у других языков?
Тут есть нюансы. Нативно компилируемые языки имеют схожие проблемы. У Rust тоже есть проблема с временем компиляции. Golang компилируется удивительно быстро. Оба утверждают, что решили проблему управления зависимостями, но их решения все еще имеют ограничения и свои собственные проблемы. Оба имеют системы управления пакетами, которые извлекают исходный код из Git-репозиториев и собирают зависимости на компьютере разработчика. И оба по-прежнему часто зависят от известных C-библиотек, которые они ожидают найти в системе. Предварительно скомпилированные и доставленные другим менеджером пакетов.
Есть способы достичь того же результата и с помощью C++, используя один из менеджеров пакетов CMake, например CPM, или систему сборки, такую как Bazel, которая может извлекать зависимости из Git-репозиториев и собирать их на лету.
Но у этого подхода есть ограничения по масштабу. Это значительно менее серьезная проблема для Golang с его сверхбыстрой скоростью компиляции, но, безусловно, проблема для Rust и C++. Ее можно решить только с помощью эффективных стратегий кэширования, что само по себе непросто. Но это уже тема для другого поста.
Скоро пройдет открытый урок, посвященный ускорению матричного умножения на C++. На этом занятии рассмотрим способы хранения матриц в памяти, сравним по скорости исполнения различные алгоритмы умножения и обсудим причины отличий во времени исполнения. В результате научитесь писать микробенчмарки на C++ с использованием библиотеки Google Benchmark и узнаете, как ускорить операции умножения матриц.
Записаться на бесплатный урок можно на странице специализации "C++ Developer".
Комментарии (7)
Rustified
31.05.2023 13:35+1Нууу, я уж думал пришло время тряхнуть легаси и помянуть чертей обратной совместимости, а тут инфраструктура. Она, конечно, тоже важна, но я думаю, что раздражающие аспекты языка поприоритетнее будут когда дело касается таких опросов
DancingOnWater
31.05.2023 13:35В любом долгоживущем языке проблем с/, вызванных обратной совместимостью пруд-пруди. Но беда в том, что без оной, головняка в порядки больше. И если для библиотек, зачастую можно пережить (хотя на моей практике были и те случаи, когда ноша уже неподъёмна), то вот в конструкции языка - это ад.
domix32
31.05.2023 13:35Ну, скажем отсутвие модулей во много было связано именно с обратной совместимостью с Си. И это одна из наиболее мажорных проблем, ведущая к проблемам как со временем компиляции и таки и той самой дистрибуцией библиотек. Остаётся надеяться, что компиляторы таки запилят полноценную поддержку этой фичи.
DancingOnWater
31.05.2023 13:35Мне всегда казалось, что модули изобрели уже после того, как C++ ушел в массы. А ввести модули пытались еще в С++11, но поняли что для этого надо некисло перелопачивать компиляторы. Дошли только сейчас.
domix32
31.05.2023 13:35некисло перелопачивать компиляторы
Собственно это как раз второй уровень легаси. В 10-х годах другие языки стали набирать обороты и составлять конкуренцию в нишах плюсов и стали подгонять скорость появления новых фич как в компиляторах, так и в самом языке.
snk
31.05.2023 13:35У Гугла тоже проблема с систематизацией подхода добавления зависимостей. У них часть проектов с бейзелем собирается , часть с симейком. Сравните репу filament и medipipe. Но в обоих случаях: большинство зависимостей - либо физически скопированные морсы (как у случае с филаментом ), либо ссылка на внешнмй опенсорс гит репо (как в случае с бейзел сборкой мелиапайпа). Всякие либджепеги и тензорфлоу. Хотя я думаю, что здесь дело в том, что Гугл покупает эти проекты вместе с командой разработки , а не разрабатывает с нуля.
x2v0
Правильное название Spack - Spack