Дорожная карта навыков разработчика на C++
Джеймс Гослинг как‑то сказал, что Java — это C++, из которого убрали все пистолеты, ножи и дубинки, однако практика показывает, что «ножи и дубинки» становятся классным инструментом в руках опытных разработчиков. В общем, немалая часть проклятий в адрес C++ объясняется элементарным «вы просто не умеете его готовить». Мы в «Лаборатории Касперского» умеем готовить «плюсы» и поэтому любим их. C++ — низкоуровневый язык, который позволяет работать с железом и писать быстрый код и при этом содержит массу возможностей. В экосистеме «плюсов» куча проработанных паттернов, best practices и готовых библиотек под разные задачи. Язык динамично развивается —, но сохраняет обратную совместимость.
В этой статье мы с помощью карты покажем, какие навыки и знания нужны разработчику на C++. Естественно, разбирать путь развития «плюсистов» будем на собственном примере — тем более что у нас в «Лаборатории Касперского» много очень разных проектов с отличающимися задачами. Однако наша карта по большей части универсальна и будет полезна всем, кто хочет развиваться в разработке на C++.
В этой карте мы разбили по блокам навыки, которые считаем необходимыми для реальной коммерческой разработки на C++, и показали, для каких задач и продуктов подходят их разные сочетания. За точку отсчёта приняли отличное знание C++: когда разработчик знает нюансы и тонкости языка и понимает, как он работает. Этот опыт формируется за 3–4 года работы с C++ на реальном проекте.
Что будет в статье
Общие знания и навыки
Знания и навыки разработки под разные операционные системы
Какие продукты пилим
Для начала расскажем, из каких блоков состоит карта, потом более подробно рассмотрим каждый блок и чем занимаются разработчики на разных проектах и в разных продуктах.
Что входит в эту схему
Общие знания и навыки
Какое бы направление работы ни выбрал разработчик на C++, всегда будет универсальный набор знаний и навыков, без которых не обойтись. Каждый «плюсист» должен знать основы языка и Computer Science, писать хороший код, грамотно работать с многопоточкой и иметь базовый набор софт‑скиллов для комфортного взаимодействия с командой.
Отличное знание C++
Это как раз об универсальной основе. По нашему опыту, многие разработчики пишут на C++ так, как будто это условный C#, — то есть совсем не погружаясь в тонкости языка и не зная, как он работает «под капотом». C++ — это язык для низкоуровневых задач, который выбирают за возможность быть ближе к железу и оптимизировать скорость выполнения кода. А значит, доскональное понимание того, как на самом деле работает язык, на чём он основан, как исполняется код, совершенно необходимо.
Это подразумевает, что разработчик знает и понимает:
как устроены и чем отличаются структуры данных, какие проблемы они решают и какую из них стоит использовать в той или иной задаче;
как устроены стандартные контейнеры внутри std: vector, std: string, std: list, std: map;
как работают исключения, какие у них есть преимущества и недостатки;
современные стандарты C++ — 17 и 20. Необходимо не только знать их, но и уметь обоснованно применять на практике нововведения языка. То есть там, где это действительно необходимо и помогает сделать код лучше;
разницу между design-, compile- и runtime —, а также не боится шаблонов.
Конечно, все эти навыки отслеживаются не каким-то тестом с галочками и вариантами ответов. Мы практикуем формат открытого общения — по ходу беседы глубина понимания всех необходимых областей знания быстро становится очевидна. Конечно, всегда есть шанс кого-то обмануть, даже интервьюера-эксперта, но, как правило, когда общаешься с кандидатом один на один, ты все равно чувствуешь, поверхностные у него знания или глубокие.
(@atotmakov) Head of Core Technologies and B2B Development, «Лаборатория Касперского»
Умение писать код
Писать хороший код — значит стройно и четко излагать свои мысли в виде команд, понятных компилятору. Этот навык неплохо проверяется даже без лайвкодинга или просмотра гитхаб-профиля кандидата: если разработчик может ясно излагать свои мысли словами, чаще всего с написанием хорошего кода проблем тоже не возникает. Поэтому формат интервью отлично подходит для такой проверки и позволяет понять, как мыслит кандидат. На собеседовании мы всегда просим кандидата порассуждать вслух и задаём наводящие вопросы.
Вот какие моменты мы стараемся проверить на интервью:
Умение читать чужой код, находить ошибки в коде и дизайне. Каждый разработчик больше времени тратит на чтение чужого кода, а не на создание своего. Если разработчик не умеет отлавливать ошибки в коде и архитектуре, процесс код-ревью будет неэффективным, а готовый продукт быстро потребует серьёзного рефакторинга.
Соответствие принципам KISS. Хороший код — простой код. Излишнее усложнение ведёт к проблемам поддержки кодовой базы. Да и на код-ревью разбирать такой код и отлавливать ошибки будет гораздо сложнее. Что опять же приведёт к необходимости скорого рефакторинга и багам в продукте.
Умение упрощать и декомпозировать сложные задачи. Проще изготовить 500 стандартных кирпичей и сложить из них стену, чем произвести один большой пятисоткратный кирпич. То же и с программированием: сложные недекомпозированные задачи влекут за собой сложный некрасивый код и неудачные архитектурные решения.
Умение разбивать код на сущности. Собственно, стандартное требование ООП: функции и классы не должны решать посторонних задач (Single-responsibility principle), но и не должны быть слишком «специализированными». Обе ошибки усложняют чтение и понимание кода, делают его плохо поддерживаемым и потенциально забагованным.
Умение понятно именовать сущности. В идеале по названию функции должно быть понятно, что она делает (даже без комментариев), по названию класса — какое место в иерархии он занимает, какие свойства и методы объекта может описывать, по названию переменной — что в ней хранится и для чего она вообще нужна.
Работа с многопоточными приложениями
Самое важное в работе с многопоточкой — это внимательность и умение смотреть на задачу в целом, а не на отдельные её блоки. Необходимо чётко понимать, какие операции в коде стоит защищать, а какие — необязательно (область действия «лочки» должна быть минимально возможной). Пригодится и знание сложных примитивов синхронизации — однако применяя их, особенно важно помнить о принципе KISS.
Опыт коммерческой разработки
Увы, без этого никак не отработать важные для профессионального программиста навыки: отлавливание ошибок в коде, работа итерациями, понимание требований к продукту, умение поддерживать продукт после релиза.
С опытом коммерческой разработки всё может быть довольно гибко — тут многое зависит от кандидата. Да, в среднем понадобится опыт от двух лет. Однако бывает, что на собеседование приходят люди с двадцатилетним стажем и не подходят нам, а бывает, что приходит стажёр-студент старших курсов — и к окончанию института уже становится крепким мидлом.
(@atotmakov), Head of Core Technologies and B2B Development, «Лаборатория Касперского»
Универсальные требования
В этот раздел мы включили набор универсальных требований, которые не относятся к C++, но важны для работы в любой нашей команде:
знание базовых алгоритмов и структур;
хороший технический английский;
софт-скиллы. Тут достаточно просто «взрослого» подхода к работе: предупреждать заранее, если что-то не получается сделать в оговорённый срок, не замалчивать личные и рабочие проблемы и т. п.
На этом заканчивается блок универсальных знаний и навыков, который необходим для работы в любом нашем продукте. Эти навыки — общие для всех, но их уже достаточно, чтобы попасть в направления:
Знания и навыки разработки под разные операционные системы
Разница между операционками на уровне прикладного программиста — не очень большая. А знания, полученные на одной платформе, легко конвертируются в другую: например, у нас есть опыт, когда разработчики, писавшие драйверы и низкоуровневые компоненты под Windows, безболезненно переходили на Mac-направление.
С библиотеками примерно то же самое — например, знание специфических Win-библиотек типа MFC, ATL, WinSock вряд ли понадобится. Чаще всего мы используем универсальные библиотеки, подходящие для разных операционок (например, STL или Boost), а задачи у прикладных программистов универсальные: многопоточность, межпроцессное взаимодействие.
Windows
С WinAPI и пониманием Windows ситуация неоднозначная: в некоторых командах достаточно знаний на уровне продвинутого пользователя операционки, в других — понадобится глубокое знание WinAPI, а командах, которые разрабатывают драйверы и исследуют вредоносное ПО, надо понимать устройство Windows в мельчайших деталях. Но независимо от команды точно понадобится умение работать с WinDbg и PerfLog.
Чтобы лучше изучить подкапотное устройство Windows и то, как писать драйверы под Win-системы, я бы порекомендовал, классику жанра — «Внутреннее устройство Microsoft Windows. Основные подсистемы ОС» Алекса Ионеску и Дэвида Соломона. Что касается WinAPI, то тут я не могу посоветовать чего-то конкретного — нет какой-то книги, которая отвечает на все вопросы. Однако есть ряд ресурсов, которые очень пригодятся: например, специализированные форумы на msdn, онлайн «Книгу внутренних компонентов Windows» и поизучать раздел Sysinternals на сайте Microsoft.
(@atotmakov), Head of Core Technologies and B2B Development, «Лаборатория Касперского»
В каких продуктах нужны эти знания и навыки:
Linux
Linux — стандарт для серверов, да и на десктопах он встречается часто. Поэтому у нас есть продукты и для этой операционки. Кстати, мы делаем его под разные аппаратные платформы, в том числе x86, ARM и «Эльбрус» (а разработка под разные аппаратные платформы — крутой опыт любого «плюсовика»).
C Linux связаны логичные задачи: работа с бизнес-логикой продукта, создание новой и поддержание уже существующей функциональности (кстати, какого-то древнего легаси у нас нет, всё современно и приятно), сертификация продукта в госорганах, анализ различных инцидентов (надо разбирать дампы памяти и логи продукта, мониторить производительность и стабильность ПО).
В каких продуктах нужны эти знания и навыки:
macOS
Ситуация с разработкой под macOS похожа на разработку под Linux и Windows: хотя обычно программирование под macOS подразумевает использование нативных Objective-C и Swift, в реальности нам никуда не деться от от C++ — всё-таки это основной язык для наших продуктов и переписывать логику продукта на Swift просто потому, что это нативно, конечно же, никто не станет.
То есть разработчикам всё равно придётся использовать внешний код на C++, чтобы не раздувать кодовые базы и переиспользовать готовые кросс-платформенные решения. К тому же на плюсах написаны многие готовые библиотеки, предоставляемые сообществом или сторонними вендорами.
Именно поэтому бизнес-логику, системные перехват и интеграцию выгодно писать на C++, а нативный стек Apple использовать только там, где без него не обойтись: пользовательский интерфейс, интеграция с системными интерфейсами. Есть и ещё одна особенность: у Swift отсутствует интероп с C++, а значит, не обойтись и без старичка Objective-C.
В каких продуктах нужны эти знания и навыки:
Работа с железом
Про KasperskyOS мы недавно писали на Хабре. ОС мы разрабатываем с нуля и сейчас активно расширяем её и портируем на разные платформы, поэтому ищем людей, которые могут создавать с нуля драйвера и сервисы. C++ используется для разработки самого ядра ОС, драйверов для разных платформ и продуктов, которые будут работать на KasperskyOS.
Здесь можно поучаствовать в разработке ядра ядра KasperskyOS.
Какие продукты пилим
Общие компоненты защиты для всех пользовательских продуктов
Это ядро всей защиты продуктовой линейки «Лаборатории Касперского». За этим направлением стоит CoreTech — R&D-направление, которое выстраивает фундамент для всех продуктов компании. Внутри CoreTech — несколько команд, каждая со своими задачами. Объединяет их то, что они пишут кросс-платформенный код, который переиспользуется в продуктах под все операционные системы:
Traffic processing. Команда анализирует трафик на машине конечного пользователя, предоставляет удобные интерфейсы для работы с ним, и разрабатывает компоненты защиты на базе этих интерфейсов. Результат работы команды: анализаторы сетевых протоколов (SSL, HTTP/1.1, HTTP/2, HTTP/3, QUIC, WebSocket, IMAP, POP3 и т. п.), веб-антивирус, антиспам, почтовый антивирус, родительский контроль, защита от фишинга.
Crypto. Команда пишет решения для криптографической защиты информации, которые работают в различных средах выполнения: пользовательский режим ОС, режим ядра, Preboot. Разработчики анализируют подписи файлов различных форматов, создают собственный стандарт подписи на основе ГОСТов, пишут крипто-подсистему для KasperskyOS, занимаются сертификацией и реализуют стандарты PKCS11, PKI, FIPS.
Instrumental PDK. Команда разрабатывает библиотеки C++ общего характера, в том числе платформенно-зависимые. Например, внутреннюю библиотеку стандартных примитивов, собственные фреймворки, которые связывают компоненты во всех продуктах и универсальные компоненты для обновления антивирусных баз.
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки.
Консоль безопасности
Основной продукт — Kaspersky Security Center. Это консоль для удобного управления безопасностью на уровне предприятия, то есть такой аналог ЦУПа для сложных IT-систем. Security Center охватывает все платформы: облачные, физические, виртуальные машины и мобильные устройства. Основные задачи:
разработка транспортной подсистемы;
разработка подсистемы управления патчами и обновлениями.
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки.
Продукты и драйверы под Windows
Основное и самое большое направление. Это и общая для всех продуктов кодовая база, и драйверы под Windows, и виндовые продукты вроде Kaspersky Endpoint Security и Kaspersky Anti-Virus (кстати, это разные решения: первое предназначено для бизнеса, а второе — для личного использования). Windows по-прежнему остаётся платформой, на которую так или иначе равняются решения под остальные ОС: это основа всех приложений и идей, локомотив продуктовой линейки Kaspersky. Разработчикам приходится постоянно разбирать системные и продуктовые дампы, писать User-Mode-компоненты, драйверы, бизнес-логику, новые продуктовые фичи.
Откликнуться на вакансии можно по ссылкам:
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Windows
Продукты и драйверы для Linux
Под Linux у нас сразу несколько продуктов. Основной — это Kaspersky Endpoint Security (KES) для Linux, рассчитанный на рабочие станции и серверы в малом и среднем бизнесе. Внутри продукта есть несколько команд разработки, которые пишут как сам Linux-клиент, опираясь на наработки и кросс-платформенную кодовую базу основного продукта, так и драйверы под Linux. Причём приложение работает на разных архитектурах: x86, ARM и «Эльбрус».
Другой — Kaspersky Secure Mail Gateway для Linux. Он дистанционно управляет IT-инфраструктурой и защищает серверы электронной почты от угроз: спама, фишинга, вредоносных вложений. KSMG имеет кластерную архитектуру для удобства масштабирования и централизованного управления всеми серверами кластера через веб-интерфейс. А также значительно большее, чем у коллег, количество фичей в продукте. Из особенностей работы над KSMG — необходимость кодить на Python, обеспечение совместимости продукта с различными почтовыми серверами (Postfix, Exim, Sendmail), встраивание open-source-программ в комплексное решение на базе Linux, обеспечение совместимости продукта с различными дистрибутивами Linux.
Какие ещё задачи решают команды:
разработка новой логики приложения (да, у приложений под Linux есть свои уникальные фичи —, а не только переиспользование общей кодовой базы);
написание автотестов и unit-тестов для нового функционала;
поддержка выпущенных версий продукта;
анализ дампов системы и самого KES, работа над стабильностью и производительностью продукта;
мониторинг и визуализация состояния сети.
Откликнуться на вакансии можно по ссылкам:
разработка системы автоматизированной защиты рабочих станций;
разработка комплексной системы защиты почтовых серверов;
разработка системы мониторинга и визуализации состояния сети.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Linux
Продукты и драйверы для macOS
Основной продукт — Kaspersky Endpoint Security для Mac. Задачи — как и у команд клиента и драйверов под Linux, только работа идёт исключительно с платформой Mac. Хотя тут есть и разные архитектуры процессоров (и x86, и пару лет назад завезённый в десктопы и ноутбуки ARM). Как и в линуксовых командах, команда разработки под Mac добавляют в продукт свои уникальные фичи, разбирают и анализируют дампы системы и KES, пишут тесты и поддерживают уже выпущенные версии ПО.
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, macOS
Ядро KasperskyOS
В этом проекте разработчики создают собственную защищённую микроядерную операционную систему KasperskyOS (не очередной форк Linux, а ОС с собственным ядром), да ещё и под разные платформы. Она используется в IoT, VDI, транспорте, корпоративных мобильных устройствах. Тут уже понадобится не только C++, но и Си с Ассемблером для следующих задач:
прототипирование решений;
написание отдельной, real-time-версии системы;
разработка и имплементация компонент для промышленной разработки ПО;
подготовка набора тестов для верификации разработанных решений;
разработка и ревью архитектуры;
подготовка набора тестов (юнит, фаззинг) для верификации разработанных решений;
анализ и улучшение эффективности, стабильности, безопасности и масштабируемости разрабатываемых решений.
Откликнуться на вакансии можно по ссылкам:
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Работа с железом
Драйверы для KasperskyOS
Разработка драйверов для KasperskyOS под разные устройства — самостоятельное направление в рамках разработки операционной системы. Это продуктовое направление делает так, чтобы KasperskyOS работала на самом разном железе, а также занимается системными сервисами и библиотеками.
Здесь от программистов требуется умение разрабатывать ПО под разные аппаратные платформы, что тянет за собой знание не только C++, но и более низкоуровневых C и Ассемблера, деталей аппаратной реализации различных компонентов современных вычислительных систем (видеокарты, процессоры, оперативная память и т. п.).
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки
Продукты для KasperskyOS
ПО под KasperskyOS и SDK для партнёров, которое позволяет создавать новые собственные продукты под эту операционку или интегрировать уже существующие решения. Задача того же уровня сложности, которую в своё время решали Apple и Google, разрабатывая для своих мобильных платформ как ПО, так и SDK для сторонних разработчиков. Только у KasperskyOS больше платформ, версий и типов устройств.
Собственное ПО пишется для разных направлений:
встроенная безопасность (in-chip security),
мобильные устройства,
тонкие клиенты,
интернет вещей и промышленный интернет вещей (Connected Industry, умные города),
электроэнергетика.
Откликнуться на вакансии можно по ссылкам:
разработка безопасного шлюза для электронных блоков автомобиля;
разработка безопасной платформы для IoT и embedded-устройств с поддержкой облачных платформ;
разработка мобильной версии KasperskyOS для разных устройств.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки
Система контентной фильтрации
Это направление покрывает все задачи, связанные с безопасностью в текстах, — защита от спам-писем, переходов по фишинговым ссылкам, родительский контроль. Для этого приходится детектировать аномалии в поведении пользователя, искать shadow-it-сервисы, плотно заниматься защитой персональных данных пользователя. Всё это портируется на Win, Linux, BSD.
Компоненты CFR в основном реализованы на современных стандартах языка C++. Сборка компонент происходит в распараллеленной среде под самые различные win*/*nix платформы и архитектуры процессоров. Они интегрируются в продукт в виде плагинов, которые можно обновлять «на горячую» без обновления самого продукта (кстати, эти плагины как раз основаны на тех самых «универсальных компонентах для обновления антивирусных баз», которые входят в блок «Общие компоненты защиты», универсальные для всех платформ). Бизнес-логика, ответственная за детектирования, реализована в виде набора скриптов и обновляется тоже отдельно и независимо от самих компонент. Задачи разнообразные:
работа над перформансом (скорость/потребление ram и т. д.);
применение эффективных алгоритмов поиска сигнатур;
поддержка скриптов бизнес-логики, интерфейсов между движком и скриптами;
интеграция в продукты на различных ОС (Win, Linux, BSD);
сетевое low-level-взаимодействие;
парсинг различных форматов (MIME, HTML, RichText, TNEF и т. д.).
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Windows, Linux
Модуль эвристического анализа
Главный продукт — System Watcher. Это компонент проактивной защиты, который на лету определяет трояны, эксплойты и шифровальщики по шаблонам поведения, а также умеет восстанавливать пользовательские файлы и реестр после заражения. У System Watcher есть версии для Windows, Linux и macOS. Помимо разработки новых версий модуля, разработчики занимаются и поддержкой уже выпущенных версий.
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Windows/Linux/macOS
Компонент безопасности для виртуальных сред
Легкий агент — это решение для защиты облаков и виртуальных сред под платформы VMware vSphere, Microsoft Hyper-V, Citrix XenServer и KVM и интерфейс для более удобного управления компонентами защиты. Разработчики создают продукт, пишут новые фичи и поддерживают существующий код на C++. Ещё одно большое направление — разработка базовых кроссплатформенных компонентов защиты под различные типы ОС.
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Linux
Kaspersky Security Network
Kaspersky Security Network объединяет распределённую по всему миру инфраструктуру: несколько дата-центров и сотни серверов, включая виртуальные в публичных облаках. Через неё проходят аналитические данные об угрозах, которые затем преобразуются, актуализируются и используются в остальных наших продуктах. Команда KSN должна обеспечить обработку полутора миллионов запросов в секунду (медианное значение) и трафика в 5000 Тб данных в месяц, а также оперативно разбираться с запросами от продуктовых команд. Серверы работают на Linux, внутри используется несколько языков под разные задачи, но основной — C++ 17.
Основные задачи команды:
Оптимизация кода для того, чтобы ПО более рационально использовало ресурсы серверного оборудования.
Как можно быстрее отвечать пользователям, особенно в сценариях, когда антивирус пытается проверить объекты в реальном времени.
Требуется понимание принципов работы интернета и основные протоколы, так как иногда приходится отлаживать крайне интересные и занятные вещи: все простые баги мы уже починили :)
Откликнуться на вакансию можно по ссылке.
Нужные навыки: Отличное знание C++, Умение писать код, Работа с многопоточными приложениями, Опыт коммерческой разработки, Linux.
Всем спасибо за внимание!
C++ несмотря на все шуточки про выстрелы в ноги, в том числе и от самого Бьерна Страуструпа, остаётся мощным и незаменимым инструментом для системного программирования. Разработка на нём идёт быстрее, чем на C и Ассемблере, при этом язык позволяет напрямую управлять памятью и работать с железом. К тому же при должной квалификации программистов код получается вполне безопасным и даже красивым. Именно поэтому он стал основной для системного программирования в KasperskyOS.
По нашей дорожной карте видно, насколько разные и крутые задачи умеют решать толковые разработчики на C++. При этом сложно представить программиста, который мог бы разом покрыть все эти области и стать этаким «универсальным юнитом» — даже в пределах одной компании.
Конечно, наша карта в первую очередь отражает специфику задач «Лаборатории Касперского» и не включает некоторые направления разработки на C++ вроде компьютерного зрения. Однако она описывает основную часть задач «плюсовиков» и послужит полезным источником информации как для кандидатов, которые хотели бы у нас работать, так и для других компаний, которые задумываются о создании своей карты компетенций. А ещё это практически гимн в честь «плюсов» — языка, на котором уже почти 40 лет держится немалая часть системного ПО и у которого пока так и не смогли забрать корону Go, Rust или Carbon.