Юрий Белк – Full stack Developer (страница 5)
3) Проверка совместимости (опционально) – например, чтобы не ломать обратную совместимость без явного решения.
Даже без сложных проверок уже полезно, чтобы CI падал, если openapi.yaml просто “сломался”.
0.3.5. Как связываем контракт и реализации
Чтобы это не осталось словами, нам нужны практические “крючки” в коде:
– Frontend использует сгенерированный клиент/типы. Если контракт поменяли – фронт компилится или падает, и это хорошо.
– E2E тесты используют контракт как основу: например, проверяют, что эндпоинты существуют, и ответы соответствуют схеме.
– Backend на каждом языке:
– реализует маршруты, перечисленные в контракте,
– возвращает формат ошибок, описанный в контракте,
– держит совместимость.
В следующих разделах мы начнём с самого простого: GET /health, затем добавим сущность (например, users или todos) и постепенно усложним.
Итог раздела: что у нас должно получиться к концу подготовки
К этому моменту у вас должно быть:
1) Готовое окружение:
– Git настроен,
– Docker работает,
– Node + pnpm работают,
– Python/Go/Java доступны (или через devcontainer).
2) Монорепозиторий с понятной структурой:
– apps/ для приложений,
– packages/shared-contract для контракта,
– infra для docker-compose,
– tests/e2e для общих тестов.
3) Принцип OpenAPI-first:
– есть openapi.yaml,
– есть генерация артефактов,
– есть проверка/валидация контракта.
Дальше мы начнём “первую реальную вертикаль”: инфраструктура (Postgres в compose), минимальные сервисы на каждом языке и первый общий e2e‑тест, который прогоняется одинаково для любого API.
Монорепозиторий и структура
В этой книге мы будем собирать один и тот же продукт, но с разными бэкендами: на TypeScript, Python, JVM и Go. Чтобы не утонуть в папках, скриптах и «а где это лежит?», мы сразу выберем понятную модель организации кода – монорепозиторий.
Монорепозиторий – это когда весь код проекта живёт в одном Git‑репозитории: фронтенд, несколько бэкендов, общие библиотеки, тесты и инфраструктура. Звучит как «большая куча», но при правильной структуре это, наоборот, делает проект спокойнее и предсказуемее.
Почему монорепозиторий удобен именно в этой книге
У нас будет несколько реализаций одного API. Они должны:
– иметь одинаковые эндпоинты и одинаковые форматы запросов/ответов;
– проходить одни и те же e2e‑тесты;
– использовать одни и те же договорённости по ошибкам, статус-кодам, структуре JSON.
Если каждую реализацию держать в отдельном репозитории, то почти всё усложняется:
– контракт API начинает жить в нескольких копиях;
– тесты дублируются и расходятся;
– инфраструктура (Postgres/Redis и т.п.) повторяется;
– сравнивать реализации сложнее – всё раскидано по разным местам.
Монорепо решает это простым способом: всё рядом. В результате вы быстрее видите, чем отличаются подходы, а не боретесь с организацией.
Общая структура проекта
Мы используем фиксированную структуру папок. Она будет одинаковой на протяжении всей книги:
text
/apps/frontend-next
/apps/api-ts
/apps/api-py
/apps/api-java
/apps/api-go
/packages/shared-contract
/infra
/tests/e2e
Дальше разберём смысл каждой папки, и какие правила мы будем соблюдать.
apps/: приложения (то, что запускается)
Папка apps/ содержит запускаемые приложения: фронтенд и несколько вариантов бэкенда.
/apps/frontend-next
Фронтенд на Next.js. Это «лицо» продукта и удобный способ быстро проверить, что API реально работает.
Что обычно лежит внутри:
– страницы и компоненты UI;
– клиент для API (чаще всего сгенерированный);
– настройки окружений (.env.local), базовый URL до API.
Главная договорённость: фронтенд не должен знать, какой именно бэкенд работает внутри. Он должен опираться на контракт: если API соответствует OpenAPI, фронтенд работает.
/apps/api-ts
Бэкенд на TypeScript (например, NestJS). Он будет полезен как «референс» для многих команд: TypeScript часто выбирают в компаниях, где много фронтенда.