4000 строк в одном MR. Три часа на ревью, 12 замечаний, исправления - ещё 800 строк. На четвёртом заходе я закрыл вкладку и понял: проблема не в коде, а в том, что никто не знал, что именно нужно было написать.
Если ты работаешь с большими кодовыми базами, ситуация знакомая. Большие MR - симптом. Когда непонятно, что именно нужно сделать, разработчик пишет больше кода, чем требуется. Добавляет на всякий случай. Покрывает сценарии, которые никто не просил. MR растёт не потому что задача большая, а потому что границы размыты.
Другая причина - иллюзия, что проще сделать всё в одной задаче, чем декомпозировать. Кажется, что разбиение создаёт лишнюю работу. На практике монолитный MR на 4000 строк никто не может нормально проверить, и баги просачиваются в продакшн.
С AI эта проблема становится критичнее. Агент пишет код быстро, но если требования размыты - генерирует то же самое: много кода на всякий случай.
Я пользуюсь AI ежедневно. Claude Code - основной инструмент, в который можно подключить разные модели: Anthropic, DeepSeek, GPT-семейство, локальные через Ollama. И в какой-то момент заметил закономерность: чем точнее формулирую задачу, тем лучше результат. Промпты становились всё более структурированными - простые инструкции, потом шаблоны, потом что-то похожее на техническое задание.
Где проблема? Сначала я думал, что ленюсь давать AI детальные инструкции. Потом решил, что AI Agent собирает недостаточный контекст - нужен RAG или что-то подобное. В итоге понял, что проблема в обоих местах: создавать полные инструкции кажется оверкилом, а как помочь агенту собрать нужный контекст - непонятно.
Но главное - нечего проверять. Нет артефакта, на который можно указать и сказать: здесь написано одно, а сделано другое.
Идея не новая - в индустрии давно говорят о spec-driven development подходе. Я долго хотел попробовать и наконец решил проверить.
Если формализовать требования в виде спецификации до начала кодирования, то:
AI Agent будет генерировать более предсказуемый код
Результат можно будет валидировать против спецификации
Архитектура останется контролируемой
Когда AI Agent генерирует сотни строк кода за минуту, единственный способ контролировать результат - иметь формальное описание того, что должно получиться, и инструмент, который проверит соответствие реализации спецификации. О втором - в отдельной статье.
Я решил проверить гипотезу на реальном проекте - инструменте для построения архитектурных графов из Go кода. Правило простое: ни одной строчки кода без спецификации.
Первая спецификация - создать пустой проект на Go со стандартным layout. Вторая - модель графа. Третья - анализатор Go кода. За несколько дней накопилось 10 завершённых спецификаций.
Kanban-подобная организация через файловую систему:
specs/ ├── todo/ # очередь задач │ ├── 0010-feature-x.md │ └── 0020-feature-y.md ├── inprogress/ # в работе (максимум одна - WIP limit) │ └── 0005-current.md └── done/ # выполнено ├── 0001-init-project.md ├── 0003-data-model.md └── 0004-go-analyzer.md
Приоритизация через числовой префикс: меньше число - выше приоритет. Переход между состояниями - перемещение файла между директориями.
Классификация по времени на написание спецификации (T-shirt sizing):
S (Small) - до 10 минут
M (Medium) - 10-20 минут
L (Large) - больше 20 минут
Размер определяет глубину проработки. S-задача: Problem Statement и 5 Acceptance Criteria. L-задача: полные UML/C4 диаграммы, детальные Requirements, 15+ критериев приёмки. Корреляция между размером спецификации и предсказуемостью результата - прямая.
Если начинаешь с нуля - попробуй с S-спецификации. Это минимальные затраты на эксперимент.
# Spec 0001: Initialize Standard Golang Project Layout **Metadata:** - Priority: 0001 - Status: Done - Effort: S ## Overview ### Problem Statement Необходимо создать базовую структуру Go проекта для инструмента archlint согласно стандартным практикам разработки. ### Solution Summary Инициализировать Go module и создать минимальную структуру проекта. ## Requirements ### R1: Go Module Initialization - Инициализировать Go module с именем github.com/mshogin/archlint ### R2: Minimal Directory Structure - Создать cmd/archlint/ для точки входа - Создать internal/ для приватного кода - Создать pkg/ для публичных библиотек ## Acceptance Criteria - [x] AC1: go.mod создан с module path github.com/mshogin/archlint - [x] AC2: cmd/archlint/main.go существует и компилируется - [x] AC3: Директории internal/ и pkg/ существуют
Полная спецификация
Минимум деталей, максимум конкретики. AI получает чёткие границы задачи.
Средние задачи требуют диаграмм. Я экспериментировал с Sequence-диаграммами - отправлял их агенту вместе с требованиями. Заметил, что по ним AI Agent выдаёт в целом то, что ожидается.
# Spec 0006: Implement Collect Command ## Overview ### Problem Statement Необходимо реализовать команду collect для сбора архитектуры из исходного кода и сохранения графа в YAML файл. ..... @startuml title Sequence: Collect Command actor User participant "collectCmd" as CC participant "GoAnalyzer" as GA participant "saveGraph" as SG User -> CC: archlint collect . -o arch.yaml CC -> GA: Analyze(dir) GA --> CC: *Graph CC -> SG: saveGraph(graph) SG --> CC: nil CC --> User: "Graph saved to arch.yaml" @enduml .....
Полная спецификация
Sequence-диаграмма определяет порядок вызовов. AI следует ей буквально.
Большие задачи требуют нескольких диаграмм - Data Model и Sequence:
# Spec 0004: Implement Go Code Analyzer ## Overview ### Problem Statement Необходимо реализовать анализатор Go кода, который парсит исходный код с помощью AST и строит граф зависимостей между компонентами. ..... ### Data Model @startuml class GoAnalyzer { -packages: map[string]*PackageInfo -types: map[string]*TypeInfo -functions: map[string]*FunctionInfo -nodes: []model.Node -edges: []model.Edge ..... ### Sequence Diagram @startuml title Sequence: Code Analysis actor User participant "GoAnalyzer" as GA participant "go/parser" as GP participant "buildGraph" as BG .....
Полная спецификация
Для L-задач несколько диаграмм - необходимость. Data Model, Sequence, Component - вместе они задают архитектуру приложения и управляют зависимостями между компонентами.
AI ускоряет работу, но архитектуру я не делегирую: решения фиксируются в спецификации, проходят ревью и проверяются валидаторами. Однако решения редко рождаются из воздуха: я приношу первичные варианты и ограничения, агент предлагает альтернативы и подсвечивает слепые зоны. Это влияет на ход мысли, и я это осознаю. Финальное "да/нет" и ответственность лежит на мне.
У агента две зоны ответственности.
Specification Editor
Я диктую голосом сырой поток мыслей (диктую быстрее, чем печатаю). Агент приводит его к моему шаблону спецификации: раскладывает по секциям, уточняет недосказанное, формулирует требования и критерии приемки так, чтобы их можно было проверить. После этого я ревьюю и фиксирую спецификацию как исходный контракт.
Implementation Executor
Когда спецификация согласована, я отдаю её агенту на реализацию. Агент пишет код по спецификации, а я проверяю результат: ревью, валидация, итерации до тех пор, пока архитектура не станет чистой и предсказуемой.
За несколько дней - 10 завершённых спецификаций и работающий проект. Код соответствует архитектуре из диаграмм.
Чтобы проверить, насколько спецификации самодостаточны, я провёл эксперимент: дал Claude Code пустую директорию и 10 спецификаций из archlint - без доступа к исходному коду. Задача: воссоздать проект с нуля.
Результат за 20 минут:
85.5% успешность воспроизведения
100% структурная идентичность (директории, файлы, типы)
23 мутации в деталях реализации
Структура проекта воспроизведена полностью. Все acceptance criteria из спецификаций выполнены. Проект компилируется и проходит тесты.
Мутации возникли там, где спецификации описывали что делать, но не как. Критический пример: алгоритм построения sequence-диаграммы был реализован иначе - функционально эквивалентно, но с другой логикой обхода стека вызовов. Ещё одна категория мутаций - стилистические: язык комментариев, порядок функций в файлах, именование переменных.
Вывод для улучшения спецификаций: для критических алгоритмов нужен псевдокод или конкретные примеры входов/выходов. Спецификация что + как даёт более точное воспроизведение, чем только что.
Полный отчёт с каталогом мутаций: github.com/mshogin/archlint-reproduction
Чтобы спецификации оставались воспроизводимыми, все изменения должны проходить через них. Никаких доработок в режиме copilot, никаких чатов с "поправь вот это". Каждое изменение - обновление спецификации, затем реализация.
Это основной вызов. Хочется быстро поправить баг в диалоге, а не возвращаться к спеке. Но каждая такая правка - потеря воспроизводимости.
Trade-off очевиден:
Нужен результат здесь и сейчас - режим copilot быстрее
Нужна воспроизводимость - только через спецификации
Выбор зависит от контекста. Прототип или эксперимент - copilot. Продуктовый код с долгим жизненным циклом - спецификации.
Подход не решает проблемы автоматически. Он не заменяет понимание предметной области, не придумывает требования и не гарантирует хороший дизайн. Он делает ошибки видимыми раньше и заставляет держать архитектуру в рамке.
Цена: время на написание спецификаций, их ревью и итерации после валидации. Если относиться к спекам формально, всё скатывается обратно в хаос. Честно спроси себя: готов ли ты тратить 10-30 минут на спецификацию, чтобы агент реализовал её за 5-20 минут?
Детали реализации варьируются. Эксперимент с воспроизводимостью показал 23 мутации - алгоритмы интерпретируются по-разному, стилистика кода отличается. Для критических участков нужен псевдокод, а не только описание.
Я думаю, что подход работает хорошо там, где есть поставленный, сформированный и рабочий процесс. В процессах с фокусом на дисциплину, на понятные зоны ответственности, ревью, критерии готовности. Можно смотреть на этот процесс как на конвейер, доставляющий ПО 24/7.
Гипотеза подтвердилась:
AI генерирует более предсказуемый код - да, при наличии диаграмм
Результат можно валидировать - да, 85.5% воспроизводимость
Архитектура остаётся контролируемой - да, 100% структурная идентичность
Суть простая: без спецификации нечего проверять, со спецификацией - есть артефакт для валидации. Не нужен идеальный AI или идеальный промпт.
Эксперимент продолжается.
Шаблоны и примеры: github.com/mshogin/archlint
Если пробуешь spec-driven подход или уже используешь - расскажи в комментариях, что работает, а что нет.
Пишу о практике AI-кодогенерации и архитектуре в Telegram: @MikeShogin
Источник


