На какой грейд (Junior, Middle, Senior) вы себя оцениваете как C++ разработчик?

Ответ

Я оцениваю себя как strong Middle / начинающий Senior разработчик (Middle+) в контексте C++.

Аргументы для уровня Middle+:

  • Глубокое знание языка: Уверенное владение современными стандартами (C++17/20), идиомами (RAII, SFINAE, CRTP), STL, шаблонами.
  • Системные навыки: Опыт работы с многопоточностью (std::thread, std::atomic, lock-free структуры), сетевым программированием (asio/Boost.Asio), понимание модели памяти.
  • Инструменты: Повседневная работа с CMake, системами сборки, отладчиками (GDB/LLDB), профилировщиками (perf, VTune), санитайзерами (AddressSanitizer, ThreadSanitizer).
  • Архитектура и качество кода: Участие в проектировании модулей, проведение code review, написание unit-тестов (Google Test), следование принципам SOLID/DRY.

Пример из опыта — реализация thread-safe кэша с истечением срока действия:

#include <shared_mutex>
#include <unordered_map>
#include <list>
#include <chrono>

template<typename Key, typename Value>
class TimedLRUCache {
    using TimePoint = std::chrono::steady_clock::time_point;
    struct Node { Key key; Value val; TimePoint timestamp; };

    std::list<Node> items;
    std::unordered_map<Key, typename std::list<Node>::iterator> index;
    mutable std::shared_mutex mutex; // Читатели-писатели
    size_t capacity;
    std::chrono::seconds ttl;

    void cleanup() {
        auto now = std::chrono::steady_clock::now();
        while (!items.empty() && (now - items.back().timestamp > ttl || index.size() > capacity)) {
            index.erase(items.back().key);
            items.pop_back();
        }
    }

public:
    TimedLRUCache(size_t cap, std::chrono::seconds timeToLive)
        : capacity(cap), ttl(timeToLive) {}

    std::optional<Value> get(const Key& key) {
        std::shared_lock lock(mutex); // Множественное чтение
        if (auto it = index.find(key); it != index.end()) {
            if (std::chrono::steady_clock::now() - it->second->timestamp <= ttl) {
                items.splice(items.begin(), items, it->second); // Move-to-front
                return it->second->val;
            }
        }
        return std::nullopt;
    }

    void put(const Key& key, Value val) {
        std::unique_lock lock(mutex); // Эксклюзивная запись
        cleanup();
        // ... логика вставки/обновления
    }
};

Направление роста до Senior: Углубление в архитектурное проектирование распределенных систем на C++, оптимизацию на уровне CPU cache/памяти, менторинг команды и более активное участие в выработке технической стратегии проекта.

Ответ 18+ 🔞

Слушай, а давай я тебе без этих ваших заумных HR-бланков, как есть, расскажу, кто я есть в мире плюсов. А то «мидл», «сеньор» — это всё, конечно, хорошо, но на деле-то как?

Понимаешь, я себя ощущаю как крепкого мидла, который уже на пол-жопы залез в сеньорскую лигу. Ну, типа Middle+, если по-пацански. Почему? А вот смотри.

Почему я не просто мидл, а уже с прицепом:

  • Язык знаю не по учебнику. Ну то есть не просто for и class написать. Я в этих твоих современных стандартах (C++17/20) плаваю как рыба, про RAII или SFINAE могу ночью разбудить — расскажу. STL — это моя родная стихия, шаблоны — не проблема, а не вот это вот «ой, компилятор ругается, чё делать».
  • С системой не боюсь работать. Потоки (std::thread), атомики, всякие lock-free штуки — не просто слова, а реальный опыт, от которого иногда голова болит, но зато работает. Сеть на asio поднимал — да, бывало, ебать колотить, но поднимал. Модель памяти в голове есть, а не как у некоторых — «ну, оно вроде работает».
  • Инструменты — мои друзья, а не враги. CMake, системы сборки — это моя ежедневная рутина, а не магия. Отладчик (GDB/LLDB) — это не страшно, это как второй монитор. Профилировщики, санитайзеры — это не для галочки, а чтобы реально баги искать и производительность смотреть. Без этого никуда.
  • Про архитектуру и качество уже думаю. Не просто «о, задача, надо написать функцию». Участвую в обсуждении, как модуль спроектировать, чтобы потом не охуеть от поддержки. Code review провожу и принимаю, тесты (Google Test) пишу, про SOLID/DRY не просто слышал, а стараюсь применять, чтобы код не превращался в спагетти-монстра.

Ну и чтобы не на словах, вот тебе живой пример из практики — thread-safe кэш, который ещё и протухает:

#include <shared_mutex>
#include <unordered_map>
#include <list>
#include <chrono>

template<typename Key, typename Value>
class TimedLRUCache {
    using TimePoint = std::chrono::steady_clock::time_point;
    struct Node { Key key; Value val; TimePoint timestamp; };

    std::list<Node> items;
    std::unordered_map<Key, typename std::list<Node>::iterator> index;
    mutable std::shared_mutex mutex; // Читатели-писатели
    size_t capacity;
    std::chrono::seconds ttl;

    void cleanup() {
        auto now = std::chrono::steady_clock::now();
        while (!items.empty() && (now - items.back().timestamp > ttl || index.size() > capacity)) {
            index.erase(items.back().key);
            items.pop_back();
        }
    }

public:
    TimedLRUCache(size_t cap, std::chrono::seconds timeToLive)
        : capacity(cap), ttl(timeToLive) {}

    std::optional<Value> get(const Key& key) {
        std::shared_lock lock(mutex); // Множественное чтение
        if (auto it = index.find(key); it != index.end()) {
            if (std::chrono::steady_clock::now() - it->second->timestamp <= ttl) {
                items.splice(items.begin(), items, it->second); // Move-to-front
                return it->second->val;
            }
        }
        return std::nullopt;
    }

    void put(const Key& key, Value val) {
        std::unique_lock lock(mutex); // Эксклюзивная запись
        cleanup();
        // ... логика вставки/обновления
    }
};

Видишь? Никакой магии, но и не примитив. Учтены и потоки (shared_mutex для читателей-писателей), и время жизни данных, и LRU-логика. Работает, ёпта.

А где расти до сеньора, спросишь? Да в общем-то понятно. Хочу глубже въехать в проектирование таких систем, чтобы не просто модуль сделать, а чтобы вся эта архитектурная махина из кучи сервисов на C++ летала. Оптимизировать на уровне кэшей процессора, а не просто цикл переписать. Команду больше вести, не просто свой код пилить, а другим подсказывать, направлять. И в принятии решений по проекту участвовать, а не просто техзадание исполнять. Вот тогда, наверное, и будет повод сказать «да, я senior». А пока — сильный Middle, который уже многое может и хочет больше.