Дневник тимлида C++
27 subscribers
46 photos
1 video
1 file
14 links
Откровенные заметки из жизни лида C++ разработчиков. Ситуации, проблемы, открытия и решения. Для обсуждения заходите в чатик https://t.me/teamLeadDiaryChat
Download Telegram
Привет!
Кажется нашел нормальное чтиво по работе.
Кажется нашел методичку по карьерному росту

Читать сразу после Таннебаума ахах

Ждем новой версии: «Как быть 10х крысой»))
3
Claude AI и Z AI (glm)

Помимо привычного текстового чата, современные платформы Claude.ai (от Anthropic) и Z.ai (от Zhipu AI) превратились в полноценные рабочие среды с широким набором инструментов для визуализации, анализа данных и автоматизации.

Инструменты и возможности Claude

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

1️⃣Артефакты (Artifacts): Это отдельная интерактивная панель в правой части экрана, где Claude создает и обновляет структурированный контент. В этой панели можно:

📌Запускать код: Claude может написать игру (например, «Змейку») на HTML/JavaScript, и в нее можно играть прямо в интерфейсе.

📌Работать с React-компонентами: Создавать интерактивные элементы интерфейса с анимациями и фильтрами.

📌Генерировать диаграммы и схемы: Создавать векторные SVG-схемы архитектур или организационных структур, которые можно скачивать и масштабировать.

📌Просматривать документы: Markdown-файлы и ТЗ отображаются с красивым форматированием, а не в виде сырого текста.

2️⃣Проекты (Projects): Это выделенные рабочие пространства, которые позволяют сохранять контекст между разными чат-сессиями.

📌В проект можно загружать базу знаний (PDF, таблицы, текстовые документы) объемом до 30 МБ на файл.

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

3️⃣Claude Code: Инструмент для разработчиков, работающий через терминал. Он имеет доступ к файловой системе, может выполнять bash-команды, делать git-коммиты и проводить глубокий рефакторинг кода.

4️⃣Claude Design: Экспериментальный инструмент для визуального дизайна. Он помогает создавать прототипы приложений, слайды и макеты на основе текстового описания, позволяя менять цвета и шрифты в реальном времени. Результаты можно экспортировать в PDF, PPTX или передавать в Canva для дальнейшей правки.

5️⃣Инструменты анализа и интеграции:

📌Analysis Tool: Позволяет загружать CSV-файлы для проведения эксплораторного анализа данных (EDA), очистки данных и построения графиков прямо в чате.

📌Claude for Sheets: Плагин для Google Таблиц, позволяющий использовать формулы Claude для массовой обработки данных в ячейках.

📌MCP (Model Context Protocol): Протокол, позволяющий подключать Claude к внешним сервисам, таким как базы данных Postgres, Figma, Slack или Google Drive.
Z.ai (ранее известная как Zhipu AI) — это крупная китайская ИИ-платформа, которая является одним из лидеров на рынке больших языковых моделей (LLM). Система базируется на семействе моделей GLM (General Language Model) и ориентирована на создание автономных агентов, сложную разработку кода и профессиональную визуализацию.
Ключевые возможности и модели
Платформа предлагает доступ к нескольким поколениям моделей, включая флагманские GLM-4.7 и GLM-5/5.1.

Программирование (Agentic Coding): Модели Z.ai демонстрируют результаты на уровне мировых лидеров (например, Claude Sonnet 4.5), занимая первые места в бенчмарках SWE-bench Verified и Terminal Bench 2.0. Модель не просто пишет фрагменты кода, а способна автономно проектировать архитектуру, интегрировать технологические стеки и проводить отладку в терминальных сценариях.
Мультимодальность: Система работает с текстом и изображениями, а также поддерживает генерацию видео.
Генерация готовых файлов: В отличие от многих чат-ботов, Z.ai выдает результаты в форматах .pptx (презентации), .docx, .pdf и .xlsx.
Инструменты поиска: Платформа включает Web Search API для LLM, поиск с цитированием веб-источников в чате и интеллектуальных поисковых агентов.

Дизайн и визуальные возможности
Z.ai делает ставку на «эстетику по умолчанию», стремясь минимизировать время пользователя на ручную правку стилей.

Генерация UI и веб-страниц: Модель понимает современные спецификации UI и создает визуально привлекательные макеты страниц, подбирая гармоничные цветовые схемы и структуры слоев.
Профессиональные презентации: GLM-4.7 значительно улучшила верстку слайдов. Совместимость с форматом 16:9 достигла 91%, а результаты описываются как «почти готовые к использованию».
Постеры: Улучшена типографика и гибкость цветовых решений для создания рекламных и информационных плакатов.

Режимы мышления (Thinking Modes)
Одной из уникальных технических особенностей Z.ai является гибкое управление процессом «размышления» модели:

Interleaved Thinking (Перемежающееся мышление): Модель думает перед каждым ответом или вызовом внешнего инструмента. Это позволяет корректировать стратегию на основе промежуточных результатов.
Preserved Thinking (Сохраненное мышление): Модель кэширует свои рассуждения между разными ходами диалога. Это критично для долгосрочных проектов: при добавлении функции на третий день работы ИИ может ссылаться на архитектурные решения, принятые в первый день.
Turn-level Thinking (Уровневое мышление): Пользователь может включать режим глубокого раздумья для сложных задач и отключать его для простых запросов, чтобы снизить задержку и стоимость.

Режим Agent Mode
Agent Mode — это режим автономного выполнения задач, где ИИ действует как «цифровой сотрудник».

Автономность: Вместо пошаговых уточнений система получает глобальную цель, сама разбивает её на этапы и выполняет тысячи вызовов инструментов для достижения результата.
Длинные циклы оптимизации: Модель GLM-5.1 специально оптимизирована для работы «вдолгую». Например, она способна за 600 итераций и 6000 вызовов инструментов в 6 раз ускорить работу базы данных, самостоятельно анализируя логи и исправляя ошибки.
Создание сложных систем: В этом режиме ИИ смог за 8 часов с нуля собрать в браузере Linux-подобный рабочий стол с файловым менеджером и приложениями, используя внешний цикл самопроверки.
inline constexpr

Для правильного объявления глобальных констант в заголовочных файлах в современном C++ (начиная со стандарта C++17) следует использовать комбинацию ключевых слов inline constexpr. Этот подход позволяет избежать нарушения правила одного определения (ODR) и гарантирует, что во всей программе будет существовать только одна копия переменной.
Ниже приведены подробные инструкции и лучшие практики, основанные на источниках.

1. Основной синтаксис и размещение
Наилучшим способом организации констант является их размещение внутри именованного пространства имен (namespace) прямо в заголовочном файле.
// constants.h #ifndef CONSTANTS_H #define CONSTANTS_H namespace MyConstants { inline constexpr double Pi = 3.14159; inline constexpr int MaxConnections = 100; } #endif

Почему это правильно:
constexpr: Гарантирует, что переменная является константой времени компиляции, что позволяет компилятору оптимизировать код, подставляя значения непосредственно в места вызова.

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

Namespace: Защищает от конфликтов имен с другими частями проекта.

2. Особенности для разных версий стандарта и типов
До C++17: Константы constexpr по умолчанию имели внутреннее связывание (internal linkage). Это означало, что каждый .cpp файл, включающий заголовок, получал свою независимую копию переменной, что могло приводить к раздуванию бинарного файла и лишнему расходу памяти.

C++17 и выше: Использование inline дает переменной внешнее связывание (external linkage). Линкер дедуплицирует определения, и программа использует один экземпляр данных.

Статические члены классов: Важно помнить, что в C++17 статические члены класса, объявленные как static constexpr, являются неявно встраиваемыми (inline). Для них ключевое слово inline можно не указывать.

3. Работа со строковыми константами в Qt

В контексте Qt-разработки важно учитывать типы данных:
QString нельзя объявить как constexpr: Этот класс имеет нетривиальный конструктор и не является литеральным типом, поэтому его нельзя вычислить на этапе компиляции.

Рекомендуемый подход: Для строковых констант используйте inline constexpr const char* или std::string_view (C++17).

Производительность в Qt:

Известно, что использование QLatin1String или QStringLiteral предпочтительнее для часто используемых строк, так как это снижает нагрузку на преобразование кодировок (UTF-8 в UTF-16) во время выполнения.

Преимущества этого метода
Эффективность памяти: Только одна копия каждой константы в памяти приложения.

Безопасность типов: В отличие от макросов #define, константы имеют строгую типизацию и область видимости.

Удобство поддержки: Изменение значения в одном заголовочном файле автоматически распространяется на весь проект.

Скорость: Компилятор может использовать значение константы для вычислений прямо во время сборки (например, для задания размеров массивов).

Лучшая практика: Если ваш компилятор поддерживает C++17, всегда отдавайте предпочтение inline constexpr для глобальных констант в заголовочных файлах.
1🔥1
В стандарте C++26 реализована статическая (компиляционная) рефлексия (предложение P2996), которая позволяет программе «инспектировать» саму себя и генерировать новый код во время компиляции. Это крупнейшее обновление языка со времен введения шаблонов, которое Херб Саттер назвал «ракетным двигателем для выражения эффективных абстракций».
Ниже приведен детальный разбор того, как устроена эта технология согласно источникам:
1. Ключевые операторы и синтаксис
Механизм рефлексии в C++26 строится вокруг двух новых базовых операций:
Оператор рефлексии (^): Применяется к сущности языка (типу, объекту, пространству имен, члену класса) и превращает её в объект метаданных. Результат этой операции всегда имеет один и тот же тип — std::meta::info (так называемое «стирание типов» или type-erased metadata).
Сплайсер или оператор «распаковки» ([: ... :]): Выполняет обратное действие — превращает объект метаданных обратно в грамматический элемент C++ (тип, выражение или имя), который можно использовать прямо в коде. Например, [: ^T :] вернет сам тип T.
2. Пространство имен std::meta
Для работы с метаданными в стандартную библиотеку добавлен набор функций времени компиляции (метафункций), находящихся в std::meta. Основные инструменты включают:
members_of: Извлекает вектор объектов рефлексии для всех членов типа или пространства имен.
nonstatic_data_members_of: Позволяет получить список только нестатических полей данных структуры или класса.
enumerators_of: Возвращает все значения перечисления (enum).
name_of (или identifier_of в новых ревизиях): Позволяет получить строковое имя объекта рефлексии.
3. Компиляционный цикл template for
Для эффективной обработки полученных метаданных вводится новая управляющая конструкция — template for. Она позволяет итерироваться по набору объектов рефлексии прямо во время компиляции, разворачивая тело цикла для каждого элемента. Это избавляет разработчиков от необходимости использовать сложные рекурсивные шаблоны или макросы для обхода полей структур.
4. Дополнительные возможности: Аннотации и Параметры
Рефлексия в C++26 выходит за рамки простого перечисления полей:
Рефлексия параметров функций (P3096): Позволяет получать типы и имена параметров функций, работать с конструкторами и операторами.
Пользовательские аннотации (P3394): Разработчики могут помечать элементы кода собственными аннотациями в формате [[=constant-expression]]. Эти аннотации доступны для чтения через рефлексию и позволяют настраивать логику кодогенерации (например, переопределять имена полей при сериализации).
5. Особенности реализации и преимущества
Императивный стиль: В отличие от старого метапрограммирования на шаблонах, работа с рефлексией идет в привычном стиле с использованием циклов и условий.
Безопасность и ошибки: Ошибки рефлексии теперь обрабатываются через compile-time исключения, которые можно ловить и обрабатывать в процессе сборки.
Zero-overhead: Рефлексия не увеличивает размер бинарного файла и не замедляет работу программы в рантайме, так как вся магия происходит на этапе компиляции.
Универсальность: Стандартная рефлексия решает задачи автоматической сериализации (в JSON и др.), создания ORM (маппинг объектов в базу данных) и конвертации enum в строку без внешних инструментов генерации кода.
Статус поддержки: На текущий момент (март 2026 года) техническая работа над C++26 завершена. Рефлексия уже частично реализована в ветках разработки компиляторов GCC 16 и Clang (проект clang-p2996). Попробовать её можно в Compiler Explorer (godbolt.org), используя флаги -std=c++26 -freflection.
Инверсия зависимостей в Chromium.
Часть 1 .

Давно ничего не писал. Пост про прошлое лето так и остался в блокноте. Напишу немного про архитектуру.

Решил запилить серию постов про инверсию зависимостей.
Подойти к вопросам, связанным с DI.

Но сначала хотелось бы рассмотреть примеры реализаций IoC в опенсорсе.

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

Проекты демонстрировал новичкам. До Chromium browser уже дошли. Хотелось еще рассмотреть парочку повседневных программ. Знаю музыкальные и видео редакторы.

Кажется, что весь опенсорс очень сложный. Справедливо для Chromium. Посмотрели другие проекты и остались довольны. Код очень структурирован комментариями вставками и пометками. Буду добавлять ссылки. Чтоб читали не только меня.

Следите...
Инверсия зависимостей в Chromium.

ЧАСТЬ 1.1 — ВСТУПЛЕНИЕ

Заходим в исходники Chromium с джуном. Там достаточно большой проект на C++.

Джун говорит: «куда мне смотреть?».
Я говорю: «на services/service_manager».
Джун уходит ковырять chrome/browser.

Далее мы видим 2 сервиса. Живут в разных процессах, общаются через Mojo, регистрируются в Service Manager.

Зависимости инвертированы, абстракции через IDL, lifecycle управляется извне. Все четко и красиво, но сложно.
ВСТАВКА: Что такое Service Manager в Chromium

Service Manager — это компонент, который управляет сервисами в многопроцессной архитектуре Chromium. По сути - распределённый IoC-контейнер. Он не знает про конкретные реализации сервисов, он знает про интерфейсы (Mojo IDL). Сервис реализует service_manager.mojom.Service — это контракт. Менеджер решает, когда сервис запускается, в каком процессе живёт и когда умирает. Это DIP на уровне всей системы.

Новички часто думают, что IoC-контейнер - это что-то маленькое и локальное. В Chromium он распределённый: один процесс управляет сервисами в других процессах. Это как твой ServiceLocator, только вместо shared_ptr - межпроцессное взаимодействие.

📎 Service Manager README
Service Manager & Services (experimental)
Chromium Architecture Overview (Sprocket)

#chromium #IoC
Инверсия зависимостей в Chromium.

ЧАСТЬ 1.2

«Какая тут архитектура?» - мой стандартный первый вопрос.

Джун отвечает что-то про мультипроцесс, про sandbox, про то что «там какой-то Mojo». И ему становится интересно. Потому что каждый, кто открывает исходники Chromium, чувствует себя потерянным.

Но признаваться в своей потерянности нельзя - все же «разбираются» (споилер - можно, если тимлид разрешает).

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

ВСТАВКА: Mojo — это IPC с интерфейсами

Mojo — это язык, или межпроцессное взаимодействие (IPC) в Chromium, но с контрактами. Определяешь интерфейс в .mojom-файле (IDL), а генератор делает C++-биндинги, и два процесса общаются через этот интерфейс. Ни один процесс не знает про реализацию другого — только про контракт. Это DIP, только между процессами, а не классами.


Новички часто путают Mojo с «каким-то там IPC» (linux). Mojo - на первый взгляд выглядит как передача сообщений. На самом деле - это интерфейсный контракт с типизацией, версионированием и жизненным циклом. Определяется в .mojom файлах и работает между процессами.

📎 Google Mojo IDL (Medium) · Chromium IPC README (GitHub) · Mojo mailing list
Инверсия зависимостей в Chromium.

ЧАСТЬ 1.3 — КОД-РЕВЬЮ С ВОПРОСАМИ

Изоляция сервисов и управление жизненным циклом

Начинаю с осторожных замечаний: «Я тут не вижу, чтобы сервисы знали друг о друге. Они, наверное, общаются только через Service Manager».

Включаю тимлидское чутьё - по структуре директорий, по .mojom-файлам, по отсутствию прямых include - делаю предположение, и оно подтверждается.

Добавляю: «каждый сервис изолировали. Он сам не создаёт зависимости - всё приходит через Mojo». И это правда.

Что быстро понимают медленно осознают джуны (или база):

В Chromium сервис не делает new SomeDependency() - он получает интерфейс через Service Manager.

Межпроцессная изоляция и Mojo Анализ структуры директорий и заголовочных файлов подтверждает строгую изоляцию сервисов: отсутствуют прямые #include реализаций, взаимодействие строится исключительно через .mojom-интерфейсы.

Сервисы не инстанцируют свои зависимости напрямую (никакого new SomeDependency()), а получают их через Service Manager. Это классический паттерн Chromium: сервис выступает только как Consumer интерфейсов, а связывание и маршрутизация IPC-вызовов делегируются фреймворку.

Управление зависимостями внутри процесса (BrowserContext)

Если на уровне ОС/процессов изоляцией управляет Service Manager, то внутри самого браузерного процесса (например, в BrowserProcess) за жизненный цикл отвечает свой механизм - KeyedService и BrowserContextKeyedServiceFactory.

Сервисы, привязанные к профилю (BrowserContext), создаются не через std::make_shared, а через строгую систему фабрик.
BrowserContextDependencyManager содержит directed acyclic graph (DAG) зависимостей: он гарантирует, что зависимый сервис будет создан только после того, как отработает фабрика его зависимости.

При обнаружении циклической зависимости на этапе старта DependencyManager останавливает запуск (assert/LOG(FATAL)).

Почему не shared_ptr на все сервисы?

Использование std::shared_ptr для связывания сотен сервисов в кодовой базе масштаба Chromium (~35 млн строк) неприемлемо по двум причинам:

Недетерминированный shutdown:
Когда профиль закрывается, нам нужно гарантированно и в правильном порядке уничтожить все привязанные к нему сервисы (например, сначала сбросить кэш, потом закрыть соединения с БД). shared_ptr оставляет порядок освобождения на откуп аллокатору и reference counting, что приводит к плавающим багам.

Use-After-Free (UAF): Если граф зависимостей не является деревом (а в браузере он таковым не является), shared_ptr легко создают циклы, которые будут жить вечно, удерживая указатели на уже уничтоженный BrowserContext.

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


Ссылки для углубления:

📎 Profile Architecture (Chromium Design Docs)
Migrating to Profile Keyed Services (chromium-dev)
Profile Architecture (googlesource)
Инверсия зависимостей в Chromium.

ЧАСТЬ 1.4

Немного рассказываю о себе.

Напоминаю о старом програмиировании. Рассказываю, что кто-то еще помнит про COM (Component Object Model) в Windows. Там чистые абстракции через виртуальные функции в эпоху до современных фреймворков.

Напоминаю, что инверсия контроля (IoC) и внедрение зависимостей - это базовые паттерны архитектуры. Можно прочесть Бушмана. Рекомендую дедов программирования и их взгляды.

«В С++ мы исторически делали DI через интерфейсы и фабрики, Chromium просто вывел это на уровень автоматизации»

Бешусь с того, что сейчас принято диай DI ассациировать с Java.

Менторю джуна далее. Специально не ставлю его в тупик, чтобы насладиться моментом его незнания (а потом снисходительно дать ему пространство).

Ещё кофе-брейк беседа про архитектуру, и рассказываю базу и интересные нюансы.

Обычно разработчики понимают ценность DI, когда сталкиваются с тестированием: если твой класс жестко привязан к конкретному процессу или контексту (Browser::GetProfile()), написать изолированный юнит-тест без поднятия половины браузера невозможно. Выход один - внедрять зависимости через интерфейсы.

Но здесь кроется главная проблема: как заставить сотни разработчиков не ломать архитектуру и не лезть за зависимостями напрямую?

В Chromium есть документ chrome/browser_design_principles.md, где DI прописан как жесткое требование.

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

Настоящая игра в том, что в Chromium архитектурные правила, которые можно формализовать, автоматизированы.

Написал прямый вызов Browser::GetProfile() вместо инжекта? Твой коммит не пройдет PRESUBMIT-хук на CI. Точка.

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

Внедрять DI через уговоры на ревью - значит обречь проект на технический долг. Внедрять его через failing CI инженерный подход.

📎 chrome/browser design principles · PRESUBMIT.py · Presubmit Scripts docs
Google недавно опубликовала 50-страничный документ о будущем разработки программного обеспечения с использованием ИИ, и заголовок предельно ясен: вайбкодинг не масштабируется, а агентная инженерия - масштабируется, и модель ИИ, которой мы так увлечены, составляет, возможно, лишь 10% от того, что на самом деле определяет наши результаты. Остальные 90% — это инструментарий: контекст, инструменты, механизмы защиты и проверка, которые вы создаете вокруг модели.

https://readwise-assets.s3.amazonaws.com/media/wisereads/articles/the-new-sdlc-with-vibe-coding/1317.pdf
🔥21