Последний год я активно использую Claude в своей разработке, и сейчас он стал значительно сильнее в области программирования, чем был в начале этого года. Claude закрывает большую часть рутинной работы.
С каждым месяцем я всё больше передаю проекты под управление AI, что в разы повышает скорость разработки, но вместе с тем сильно понижает понимание архитектуры моих проектов.
Чтобы не терять связь с проектами, я решил внести несколько важных правил при разработке проектов с помощью AI.
В новой статье я расскажу, как я контролирую архитектуру проекта, не снижая скорость разработки и не теряя собственного понимания структуры проекта.
Технические рамки
Начиная разработку, я в первую очередь определяю технический стек будущего проекта.
В правилах нужно указать:
- языки программирования;
- фреймворки и библиотеки;
- системы управления базами данных;
- системы сборки и управления зависимостями;
- способы запуска и развёртывания приложения.
На отдельные части я ставлю строгие запреты. Например, Claude не имеет права самостоятельно добавлять новые зависимости и заменять существующие библиотеки. Если необходимо изменить стек, то сначала нужно объяснить причины и согласовать решение.
Стандарты кода
Необходимо делать большой акцент на стандартах написания кода. Для меня это является одной из ключевых задач во время программирования.
Не нужно описывать стандарты в правилах!
Во-первых, потому что большинство AI-ассистентов уже из коробки знают синтаксис и правила всех популярных языков.
Во-вторых, это не обезопасит вас от нарушений.
Используйте линтеры и статические анализаторы для строгого соблюдения стандартов написания кода.
Настраивать проверки качества кода необходимо на этапе локальной разработки — через Git Hooks, и в репозитории — через CI.
- Примеры Bash-скриптов для Git Hooks — https://github.com/prog-time/git-hooks
- Примеры CI-конструкций — https://github.com/prog-time/workflows
Документирование архитектуры
В этой части содержится самая большая проблема…
С ростом проекта растут его кодовая база и количество зависимостей. Даже если вы будете контролировать каждый этап вручную, общая картина будет постоянно расширяться, и вам будет тяжело всё это держать в своей голове.
Поэтому я считаю, что архитектуру нужно описывать внутри проекта. Не обязательно создавать десятки документов. Достаточно спроектировать несколько базовых схем, которые дают целостное представление о системе и помогают ориентироваться в проекте.
Для хранения схем можно использовать Mermaid, PlantUML или другие форматы, позволяющие держать описание диаграммы в текстовых файлах.
C4-модель
C4-модель — это набор схем, которые описывают архитектуру на разных уровнях детализации.
То, какие уровни описывать, каждый выбирает исходя из потребностей. Обычно для большинства проектов я описываю 3 уровня.
System Context — контекст системы.
На этом уровне система описывается в целом. Например, в схеме можно указать типы пользователей, платёжные сервисы, внешние API, почтовые провайдеры, системы идентификации пользователей и так далее.
Данный уровень помогает понять границы проекта.
Container — основные части системы.
На этом уровне отражаются компоненты системы: веб-приложение, фоновые обработчики, база данных, очередь сообщений и другие существенные части архитектуры.
Схема описывает компоненты системы и то, как они взаимодействуют внутри проекта.
Component — внутреннее устройство отдельных частей.
На этом уровне описываются отдельные компоненты, устройство которых важно понимать при разработке и сопровождении.
Необязательно детализировать каждый контейнер до отдельных классов, важно показать существенные границы ответственности и зависимости.
Все схемы должны быть сгенерированы в текстовом формате, чтобы они были полезны разработчику и AI-ассистенту.
Если Claude предлагает добавить новый сервис, разработчик может сначала оценить, как это повлияет на общую архитектуру, и только затем переходить к деталям реализации.
Структура базы данных
В каждом своём проекте, где требуется реляционная база данных, я вначале проектирую архитектуру базы данных, описывая таблицы, индексы и связи между таблицами.
Перед тем как создавать миграции, я создаю схему в формате ERD (Entity Relationship Diagram).
Максимально проработанная ERD-диаграмма позволяет сократить количество ошибок и понять общую картину архитектуры базы данных.
При этом миграции и ограничения в самой СУБД остаются частью реализации. Схема лишь описывает всю структуру целиком, так как в проекте могут быть сотни миграций, что усложняет чтение как для разработчика, так и для AI.
Важно обновлять данную схему при изменении структуры БД.
Схемы для сложных сценариев
Схемы, которые я рассмотрел выше, описывают архитектуру проекта, но не объясняют поведение системы.
Для сложных сценариев можно использовать дополнительные диаграммы.
Диаграммы последовательностей описывают взаимодействие компонентов в рамках одного процесса.
Если у вас интернет-магазин, то можно описать, что происходит при «оформлении заказа»:
- какие проверки запускаются;
- как создаётся запись в БД;
- как вызывается платёжный сервис.
Диаграммы состояний описывают состояния жизненного цикла конкретных объектов. Например, заказ может иметь состояния «создан», «оплачен», «отправлен», при этом на каждом этапе завязана своя логика.
Схемы потоков данных полезны, если у вас есть процессы, в которых данные проходят через несколько сервисов.
Фиксация архитектурных решений
Помимо описания существующей архитектуры, я также рекомендую описывать причины принятия решений.
Для этого существует подход Architecture Decision Records (ADR).
Данный подход предполагает хранение коротких документов, описывающих важные архитектурные решения.
Обычно ADR хранят в репозитории, например в каталоге docs/adr/. Каждое решение имеет свой номер и краткое название:
0001-choose-database.md;0002-authentication-strategy.md;0003-caching-approach.md.
Это должны быть короткие документы с описанием основных моментов:
- контекст;
- решение;
- альтернативные предложения;
- последствия;
- статус.
Такая запись позволяет оценить решение с учётом условий, в которых оно применялось.
В качестве формата написания можно использовать стандарт ASD-STE100. Это международный стандарт упрощённого технического английского языка, предназначенный для написания технической документации.
Ведение репозитория
Не могу пройти мимо этой темы, так как для меня она является одной из основных.
Первое, на что я обращаю внимание при разборе GitHub-репозиториев программистов, — это порядок внутри проектов. Я смотрю на то, как именуются ветки, какие комментарии пишутся в коммитах, как организованы релизы и создаются ли Issues.
В своей работе я придерживаюсь следующих правил:
- Все изменения вести через Issues. Вначале создаётся задача, формируется описание проблемы, а затем уже пишется код. Крупные задачи лучше разделять на более мелкие, чтобы было проще контролировать код и проводить ревью.
- В названии веток указывать номер Issue. Именование веток должно быть стандартизировано, каждая ветка должна содержать номер задачи. Конкретный формат зависит от предпочтений команды, а в своих проектах я использую формат
issues-123. Такой подход позволяет упростить навигацию по репозиторию, особенно когда AI работает с несколькими задачами одновременно. - В комментарии коммита указывать номер задачи. Это также упрощает навигацию в репозитории.
Для соблюдения всех этих правил вы можете настроить проверки через Git Hooks. Git позволяет отлавливать любые события, внедрять свои проверки или корректировать результат.
Например, при создании коммита можно автоматически подставлять номер задачи в текст коммита, чтобы в истории коммитов было понятно, к какой задаче относится коммит.
Или можно запрещать создание ветки, если в её названии не указан номер задачи. Проверку можно проводить с помощью простой регулярки.
CI должен запускать согласованный набор проверок и совпадать с проверками Git Hooks. По мере роста проекта процесс можно усложнять!
Документация проекта
Документация проекта важна не только для разработчиков, но и для пользователей, особенно если вы разрабатываете публичный проект.
В каждом проекте есть несколько стандартных файлов, которые хранят в себе описания проекта.
README.md — один из первых документов, к которым обращается пользователь, знакомясь с проектом. Его задача — описать возможности проекта, архитектуру, требования к запуску и инструкцию по установке.
Не нужно помещать в README.md всю информацию о системе, лучше оставить его компактным и добавить ссылки на разделы основной документации.
Историю изменений можно описывать в CHANGELOG.md. В нём можно хранить историю релизов с описанием нового функционала и исправлений ошибок.
Если у вас open-source-проект, то вам точно необходимо создать CONTRIBUTING.md. В нём описать правила создания Issues, именования веток, требования к коммитам, порядок работы с Pull Request и обязательные проверки.
Дополнительно можно создать ARCHITECTURE.md и RUNBOOK.md.
ARCHITECTURE.md описывает основные архитектурные принципы, границы компонентов и ключевые зависимости. Если в проекте используются C4-диаграммы и ERD, документ может содержать ссылки на них.
RUNBOOK.md содержит инструкции по запуску и остановке сервисов, типовые диагностические действия, восстановление после распространённых сбоев и другие необходимые операционные процедуры.
Объяснения после изменения кода
Помимо понимания результата проделанной работы, также важно понимать, что делает AI-ассистент в процессе своей работы.
Необходимо требовать от AI-ассистента присылать краткий отчёт о проделанной работе:
- Что изменилось?
- Как теперь работает функциональность?
- Почему выбрано такое решение?
- Как проверен результат?
- Что осталось сделать?
Не нужно требовать полный пересказ каждого изменения, важно выделить то, что поможет разработчику при дальнейшей работе над проектом.
Опишите в правилах шаблоны для ответа после выполнения задачи, дополнительно можно потребовать возвращать ссылки на Issues.
Настройка единого процесса
Все описанные практики должны выстраиваться в единый процесс. Вы сами определяете, что для вас нужно, исходя из сложности проекта и степени вовлечённости.
Мой рабочий цикл обычно выглядит так:
- Постановка задачи. Создаём Issues, описываем проблемы и то, каким мы видим архитектуру проекта.
- Анализ. Просим AI-ассистента провести анализ задачи, предложить свои идеи и при необходимости декомпозировать задачу или создать дополнительные подзадачи.
- Фиксируем решения. После того как определились с архитектурой, фиксируем её в формате диаграмм и ADR-документов.
- Реализация. AI-ассистент выполняет работу на основе ранее созданного плана. В процессе выполнения могут появиться дополнительные подзадачи, которые должны быть заведены и пройти тот же цикл.
- Тестирование. На этом этапе проверяем качество кода с помощью линтеров и статических анализаторов, а также проверяем покрытие автотестами.
- Документация. При любом, даже малейшем изменении системы корректируем документацию. Актуализируем README, ADR и CHANGELOG. Если у проекта отдельная документация, её также нужно актуализировать.
- Проверка. Изучите отчёт о выполнении задачи, сопоставьте результат с критериями приёмки, проведите необходимый code review и подтвердите правильность выполнения задачи.
- Сохранение знаний. Если в ходе выполнения задачи вы обнаружили нестандартное поведение AI-ассистента, то обязательно скорректируйте файлы правил.
Итог
Использование нейросетей для написания кода значительно ускоряет работу программиста, но вместе с тем увеличивает риск ошибок.
Главный риск заключается в том, что человек не успевает осмыслить последствия изменений, которые вносит AI-ассистент.
Чтобы минимизировать данные проблемы, нужно организовать работу так, чтобы знания о проекте не зависели от памяти отдельного разработчика или контекста одной сессии AI-ассистента.