14 KiB
Правила разработки
1. Назначение документа
Этот документ фиксирует, как именно должен разрабатываться проект:
- в каком стиле писать код;
- как применять
TDD; - как вести git;
- как принимать архитектурные решения во время реализации.
Цель документа - сделать процесс разработки предсказуемым и не дать проекту расползтись по качеству.
2. Базовые принципы
- сначала проектирование, потом код;
- сначала тест, потом реализация;
- идти по циклу
RGR + commit; - сначала маленький модуль, потом интеграция;
- одна ответственность на один модуль;
- никаких "временных" god-struct и "потом распилим".
3. Основной процесс разработки
Рекомендуемый цикл для каждой фичи:
- Зафиксировать контракт в документации или тесте.
- Написать failing test.
- Реализовать минимальный код, который проходит тест.
- Выполнить refactor без изменения поведения.
- Сделать атомарный commit.
- Если логически завершена часть фичи, сделать push.
- Добавить integration test, если фича выходит за границы одного модуля.
- Обновить документацию, если изменился контракт.
Это и есть базовый TDD-процесс проекта в форме Red -> Green -> Refactor -> Commit.
4. RGR + commit
Для проекта принимается классический цикл:
RedGreenRefactorCommit
Правила:
- без commit после завершенного
RGR-цикла шаг не считается завершенным; - commit должен фиксировать одну логическую единицу изменения;
- если несколько
RGR + commitлогично закрывают часть фичи, после этого делается push; - не нужно ждать полного завершения всей feature branch, чтобы отправить изменения в удаленный репозиторий.
5. TDD-правила
5.1. Что пишется через TDD обязательно
crank-schemacrank-mappingcrank-registrycrank-runtimeadmin-apimcp-server- YAML import/export
- versioning logic
- любая backend-логика, меняющая доменный контракт, поведение runtime, storage, auth, execution или transport
5.2. Что допускается делать сначала каркасом, потом тестами
- frontend layout;
- frontend copy, UX cleanup и визуальная реструктуризация;
- wiring приложений;
- пустые
axumhandlers; - начальный scaffold
cargo workspace.
Но как только появляется логика, она должна переходить под тесты.
Практическое правило проекта:
- для backend
TDDобязателен; - для frontend строгий
TDDне требуется на уровне верстки, копирайта и UX-правок; - frontend-изменения все равно должны подтверждаться проверками, smoke-тестами или e2e там, где это уместно.
5.3. Правило минимального шага
Нельзя писать сразу большую "умную" реализацию на сотни строк без промежуточных тестов.
Особенно это запрещено для:
- mapping engine;
- protobuf normalization;
- publish flow;
- YAML import pipeline.
6. Правила по коду
6.1. Стиль модулей
- модуль должен иметь одну четкую ответственность;
- публичный API модуля должен быть минимальным;
- если модуль начинает решать две разные задачи, он делится;
utils,common,helpersдопускаются только в очень редких случаях и с узким смыслом.
6.2. Стиль структур
- маленькие
struct; - явные типы вместо "универсальных" JSON-объектов там, где контракт уже известен;
- protocol-specific поля не смешиваются в одной структуре без discriminated union;
- методы на
implне должны тащить инфраструктурные зависимости.
6.3. Самоописывающийся код
Для проекта принимается подход self-documenting code:
- названия функций, переменных, типов и модулей должны быть достаточно точными, чтобы код читался как текст;
- комментарии в коде считаются исключением, а не нормой;
- если код хочется "объяснить" комментарием, сначала нужно попытаться упростить названия и декомпозицию;
- комментарии в коде по умолчанию не пишутся.
Допустимое исключение:
- редкий комментарий для неочевидного инварианта или ограничения внешнего протокола.
Но базовое правило проекта:
- комментарии в коде исключаем.
6.4. Язык кода и git
Для проекта фиксируется:
- commit messages только на английском языке;
- комментарии в коде только на английском языке, если они все-таки неизбежны;
- имена типов, функций, переменных, модулей и тестов только на английском языке.
6.5. Стиль ошибок
- использовать типизированные ошибки;
- ошибка должна сохранять стадию отказа: schema, mapping, adapter, external, persistence;
- нельзя сваливать все в строковый
anyhowна границах домена.
6.6. Стиль async
asyncиспользовать только там, где есть реальная I/O или async boundaries;- не превращать чистую доменную логику в
asyncбез причины; - не смешивать чистую валидацию и сетевые вызовы в одном методе.
7. Правила проектирования
Проект разрабатывается с опорой на Clean Architecture.
7.1. Что нельзя делать
- один большой
OperationServiceна весь проект; - один
AppStateсо всеми зависимостями мира; - один adapter с
match protocolна сотни строк; - доменные методы, которые знают про SQL, HTTP и файлы одновременно;
- скрытую магию в mapping generation.
7.2. Что нужно делать
- использовать
traitна инфраструктурных границах; - использовать
service/use caseдля orchestration; - держать доменные типы отдельно от DTO;
- создавать explicit runtime view для исполнения;
- держать published flow отдельно от draft editing.
7.3. Dependency rule
Для проекта фиксируется dependency rule:
- внешние слои могут зависеть от внутренних;
- внутренние слои не зависят от внешних;
- домен не знает про HTTP, SQL, storage и transport;
- adapters и repositories реализуют контракты, заданные ближе к домену.
7.4. Open-core правило
Для проекта фиксируется дополнительное правило:
- код
Communityв целевой split-модели живет вcrank-community; - коммерческий код не должен попадать в public repository "на будущее";
- в public code допустимы только extension seams, capability flags и контракты для private implementations;
- edition gating должно проверяться на серверной стороне, а не только в UI.
8. Git workflow
8.1. Remote
Удаленный репозиторий проекта:
git@github.com:bsodfather/crank.git
8.2. Ветки
Фиксируем такой workflow:
main- стабильная ветка;- крупные фичи делаются в отдельной ветке
feat/<feature-name>; - после merge feature-ветка удаляется и в
origin, и локально.
Примеры:
feat/workspace-scaffoldfeat/schema-modelfeat/mapping-enginefeat/admin-api-v1
8.3. Коммиты
Коммит должен:
- быть маленьким;
- содержать одну логическую единицу;
- по возможности включать тесты вместе с реализацией;
- не смешивать refactor и новую фичу без причины.
Коммиты пишутся только на английском языке.
Хороший порядок:
test: add failing tests for schema validationfeat: implement schema validatorrefactor: simplify schema field traversal
8.4. Push policy
Фиксируем такую политику push:
- push делается периодически;
- не нужно ждать полного закрытия feature branch;
- push делается после одного или нескольких логически связанных
RGR + commit; - push должен оставлять ветку в консистентном состоянии.
8.5. Current delivery mode
Для текущего этапа проекта фиксируется отдельное правило доставки:
- рефакторинг;
- небольшие исправления;
- UX/copy cleanup;
- documentation-driven remediation
по умолчанию вливаются напрямую в main в GitHub без обязательного PR.
PR остается допустимым, если:
- изменение большое;
- меняется публичный контракт;
- нужен отдельный review gate;
- работа идет рискованным или спорным срезом.
8.6. Merge cleanup
После merge в main обязательно:
- удалить remote branch;
- удалить локальную branch;
- не оставлять merged feature branches висеть в репозитории.
9. Definition of Done
Фича считается законченной, если:
- код реализован;
- unit/integration tests добавлены и проходят;
- документация обновлена, если изменился контракт;
- нет явного архитектурного долга "починим потом";
- фича вписывается в принятые границы слоев.
При этом для каждой конкретной фичи должен существовать свой локальный DoD, описанный в плане реализации.
10. Порядок принятия решений
Если в ходе реализации возникает спорное решение:
- Проверяется текущая документация.
- Если решение уже зафиксировано, следуем ему.
- Если решение не зафиксировано, сначала обновляется документация.
- Только после этого пишется код.
Это важно, чтобы код не начал определять архитектуру задним числом.
11. Практический итог
Для этого проекта правильный режим разработки такой:
- проектируем заранее;
- пишем через
TDDв формеRGR + commitтам, где есть логика; - двигаемся маленькими этапами;
- ведем каждую фичу в отдельной ветке
feat/<feature-name>; - пушим атомарно и периодически;
- пишем commit messages и неизбежные code comments только на английском;
- стараемся вообще обходиться без комментариев в коде за счет самоописывающегося дизайна;
- не допускаем временных архитектурных компромиссов, которые потом невозможно разгрести.