Документация и ADR
Обзор
Документируй решения, а не только код. Самая ценная документация фиксирует почему: контекст, ограничения и компромиссы, приведшие к решению. Код показывает, что построено; документация объясняет, почему это построено именно так и какие альтернативы рассматривались. Этот контекст необходим будущим людям и агентам, работающим в кодовой базе.
Когда применять
- Принимаешь значимое архитектурное решение
- Выбираешь между конкурирующими подходами
- Добавляешь или меняешь публичный API
- Выпускаешь функциональность, меняющую поведение для пользователя
- Вводишь в проект новых людей (или агентов)
- Ловишь себя на том, что объясняешь одно и то же по многу раз
Когда НЕ применять: не документируй очевидный код. Не пиши комментарии, повторяющие то, что код и так говорит. Не пиши документацию для одноразовых прототипов.
Записи об архитектурных решениях (ADR)
ADR фиксируют рассуждения, стоящие за значимыми техническими решениями. Это документация с самой высокой отдачей из всего, что можно написать.
Когда писать ADR
- Выбор фреймворка, библиотеки или крупной зависимости
- Проектирование модели данных или схемы БД
- Выбор стратегии аутентификации
- Выбор архитектуры API (REST против GraphQL против tRPC)
- Выбор между инструментами сборки, платформами хостинга или инфраструктурой
- Любое решение, которое дорого отменять
Сначала подстройся под существующее соглашение
Прежде чем создавать ADR, изучи доступный контекст репозитория на предмет устоявшегося соглашения — существующие ADR, инструкции проекта, конфигурацию или инструменты для ADR (например, файл .adr-dir). Устоявшееся соглашение перевешивает умолчания ниже. Подстройся под:
- Расположение и формат — например,
docs/adr/*.md,Documentation/Decisions/*.rst, раскладку MADR или установкуadr-tools. Соблюдай существующий каталог, расширение файлов и разметку (Markdown против reStructuredText). - Нумерацию и именование — продолжай существующую последовательность и шаблон имён (
ADR-004-Title.rst,0004-title.md, …); не начинай заново с 001 и не вводи вторую схему. - Заголовки разделов — переиспользуй набор заголовков проекта, а не навязывай набор из этого шаблона.
Если доступные свидетельства противоречат друг другу, вынеси конфликт наружу, а не вводи молча ещё одну схему. Только когда соглашение установить невозможно, применяй умолчание ниже.
Шаблон ADR
Храни ADR в docs/decisions/ со сквозной нумерацией (если в проекте не принято другое расположение — см. выше):
# ADR-001: Использовать PostgreSQL как основную БД
## Статус
Принято | Заменено ADR-XXX | Устарело
## Дата
2025-01-15
## Контекст
Нам нужна основная база данных для приложения управления задачами. Ключевые требования:
- Реляционная модель данных (пользователи, задачи, команды со связями)
- ACID-транзакции для смены состояний задач
- Поддержка полнотекстового поиска по содержимому задач
- Доступен управляемый хостинг (небольшая команда, ограниченные ресурсы на эксплуатацию)
## Решение
Использовать PostgreSQL с ORM Prisma.
## Рассмотренные альтернативы
### MongoDB
- Плюсы: гибкая схема, легко начать
- Минусы: наши данные по сути реляционные; связями пришлось бы управлять вручную
- Отклонено: реляционные данные в документном хранилище ведут к сложным соединениям или дублированию
### SQLite
- Плюсы: нулевая настройка, встраиваемая, быстрая на чтение
- Минусы: ограниченная поддержка параллельной записи, нет управляемого хостинга для продакшна
- Отклонено: не подходит для многопользовательского веб-приложения в продакшне
### MySQL
- Плюсы: зрелая, широко поддерживаемая
- Минусы: у PostgreSQL лучше поддержка JSON, полнотекстовый поиск и экосистема инструментов
- Отклонено: PostgreSQL лучше подходит под наши требования
## Последствия
- Prisma даёт типобезопасный доступ к БД и управление миграциями
- Можно использовать полнотекстовый поиск PostgreSQL вместо добавления Elasticsearch
- Команде нужны знания PostgreSQL (стандартный навык, риск низкий)
- Хостинг на управляемом сервисе (Supabase, Neon или RDS)
Жизненный цикл ADR
ПРЕДЛОЖЕНО → ПРИНЯТО → (ЗАМЕНЕНО или УСТАРЕЛО)
- Не удаляй старые ADR. Они фиксируют исторический контекст.
- Когда решение меняется, пиши новый ADR, который ссылается на старый и заменяет его.
Комментарии в коде
Когда комментировать
Комментируй почему, а не что:
// ПЛОХО: повторяет код
// Увеличиваем счётчик на 1
counter += 1;
// ХОРОШО: объясняет неочевидный замысел
// Ограничение частоты использует скользящее окно — сбрасываем счётчик
// на границе окна, а не по фиксированному расписанию, чтобы предотвратить
// всплески атак на стыках окон
if (now - windowStart > WINDOW_SIZE_MS) {
counter = 0;
windowStart = now;
}
Когда НЕ комментировать
// Не комментируй самоочевидный код
function calculateTotal(items: CartItem[]): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// Не оставляй комментарии TODO для того, что надо просто сделать сейчас
// TODO: добавить обработку ошибок ← Просто добавь её
// Не оставляй закомментированный код
// const oldImplementation = () => { ... } ← Удали, история есть в git
Документируй известные подводные камни
/**
* ВАЖНО: эту функцию нужно вызвать до первой отрисовки.
* Если вызвать после гидратации, будет вспышка нестилизованного контента,
* потому что контекст темы недоступен во время серверного рендеринга.
*
* Полное обоснование дизайна см. в ADR-003.
*/
export function initializeTheme(theme: Theme): void {
// ...
}
Документация API
Для публичных API (REST, GraphQL, интерфейсы библиотек):
Прямо в типах (предпочтительно для TypeScript)
/**
* Создаёт новую задачу.
*
* @param input - данные создания задачи (title обязателен, description необязателен)
* @returns созданная задача с идентификатором и метками времени от сервера
* @throws {ValidationError} если title пуст или длиннее 200 символов
* @throws {AuthenticationError} если пользователь не аутентифицирован
*
* @example
* const task = await createTask({ title: 'Buy groceries' });
* console.log(task.id); // "task_abc123"
*/
export async function createTask(input: CreateTaskInput): Promise<Task> {
// ...
}
OpenAPI / Swagger для REST API
paths:
/api/tasks:
post:
summary: Create a task
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskInput'
responses:
'201':
description: Task created
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
'422':
description: Validation error
Структура README
У каждого проекта должен быть README, покрывающий:
# Название проекта
Один абзац о том, что делает этот проект.
## Быстрый старт
1. Склонируйте репозиторий
2. Установите зависимости: `npm install`
3. Настройте окружение: `cp .env.example .env`
4. Запустите dev-сервер: `npm run dev`
## Команды
| Команда | Описание |
|---------|-------------|
| `npm run dev` | Запуск сервера разработки |
| `npm test` | Прогон тестов |
| `npm run build` | Сборка для продакшна |
| `npm run lint` | Запуск линтера |
## Архитектура
Краткий обзор структуры проекта и ключевых архитектурных решений.
Подробности — ссылки на ADR.
## Как участвовать
Как вносить вклад, стандарты кода, процесс пулл-реквестов.
Ведение changelog
Для выпущенной функциональности:
# Changelog
## [1.2.0] - 2025-01-20
### Добавлено
- Шеринг задач: пользователи могут делиться задачами с участниками команды (#123)
- Уведомления по почте о назначении задач (#124)
### Исправлено
- Дубликаты задач при быстром многократном нажатии кнопки создания (#125)
### Изменено
- Список задач теперь грузит по 50 элементов на страницу (было 20) — удобнее (#126)
Документация для агентов
Особое внимание к контексту AI-агентов:
- CLAUDE.md / файлы правил — документируй соглашения проекта, чтобы агенты им следовали
- Файлы спек — держи спеки обновлёнными, чтобы агенты строили правильную вещь
- ADR — помогают агентам понять, почему прошлые решения были приняты (предотвращает перерешивание)
- Подводные камни в коде — не дают агентам попасть в известные ловушки
Типовые самооправдания
| Самооправдание | Как на самом деле |
|---|---|
| «Код самодокументируемый» | Код показывает «что». Он не показывает «почему», какие альтернативы отклонены и какие ограничения действуют. |
| «Напишем документацию, когда API устаканится» | API устаканиваются быстрее, когда их документируют. Документация — первая проверка проектного решения. |
| «Документацию никто не читает» | Агенты читают. Будущие инженеры читают. Ты сам через три месяца читаешь. |
| «ADR — накладные расходы» | ADR на 10 минут предотвращает двухчасовой спор о том же решении через полгода. |
| «Комментарии устаревают» | Комментарии про «почему» стабильны. Устаревают комментарии про «что» — именно поэтому пиши только первые. |
Тревожные признаки
- Архитектурные решения без письменного обоснования
- Публичные API без документации и типов
- README, который не объясняет, как запустить проект
- Закомментированный код вместо удаления
- Комментарии TODO, висящие неделями
- Ни одного ADR в проекте со значимыми архитектурными решениями
- Документация, которая пересказывает код вместо объяснения замысла
Проверка
После документирования:
- ADR существуют для всех значимых архитектурных решений
- README покрывает быстрый старт, команды и обзор архитектуры
- У функций API задокументированы параметры и возвращаемые типы
- Известные подводные камни задокументированы прямо там, где они важны
- Закомментированного кода не осталось
- Файлы правил (CLAUDE.md и подобные) актуальны и точны