Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → OpenAPI и контрактная разработка: спецификация как источник истины

Контрактная разработка API: OpenAPI-спецификация как источник истины команды

Как организовать работу по OpenAPI: contract-first против code-first, генерация клиентов и серверных заглушек, валидация и совместная работа фронтенда и бэкенда без блокировок.

Прямой ответ

Контрактная разработка переворачивает порядок: сначала команда согласует OpenAPI-спецификацию (эндпоинты, схемы, ошибки), и только потом фронтенд и бэкенд реализуют её параллельно — фронт против моков, сгенерированных из той же спеки, бэкенд — с валидацией запросов против неё. Спецификация перестаёт быть документацией, которую никто не читает, и становится исполняемым артефактом: из неё генерируются клиенты, серверные заглушки, моки и тесты. Порог входа — один YAML-файл и редактор с валидацией; окупается схема с первого же совместного проекта двух разработчиков.

Contract-first против code-first

Code-first (FastAPI/SpringDoc/NestJS генерируют спеку из кода) удобен на старте соло-проекта: спека всегда соответствует коду физически. Слабость — контракт появляется после реализации, и согласовывать с потребителями уже нечего: API «как получилось». Contract-first требует дисциплины (спека пишется и ревьюится до кода), но даёт главное — договорённость: фронтенд не блокируется на бэкенд, ревью API происходит на уровне YAML, а ломающие изменения видны на диффе спеки до написания кода. Практика зрелых команд: contract-first для внешних и межсервисных API, code-first допустим для внутренних прототипов с последующей фиксацией контракта.

Жизненный цикл спеки в репозитории

Спека живёт в git рядом с кодом (или в отдельном репозитории контрактов при многих потребителях) и проходит те же стадии, что код: PR с диффом → ревью → merge. Обязательные элементы процесса: линтинг спеки (Spectral — правила стиля и антипаттерны, подключается в git-хуки по образцу статьи про pre-commit); проверка ломающих изменений (oasdiff/openapi-diff в CI — удаление поля или сужение типа не пройдёт незамеченным); версионирование (URL /v1/ или заголовок, ломающие изменения — новая мажорная версия). Дисциплина «спека меняется PR-ом» превращает API-разговоры из «ты сломал мой запрос» в читаемый дифф.

Генерация: клиенты, заглушки, моки

Из одной спеки openapi-generator (и аналоги) выдаёт: типизированные клиенты под десятки языков (фронтенд получает типы запросов/ответов и не пишет их руками), серверные интерфейсы-заглушки (бэкенд реализует методы, а маршрутизацию и валидацию берёт генератор), и моки для мок-сервера. Моки — критичный элемент параллельности: Prism и подобные поднимают по спеке сервер, отвечающий примерами (examples в спеке!) — фронтенд стартует в день согласования контракта. Тестовый контур замыкается: интеграционные тесты валидируют ответы реального бэкенда против спеки (schemathesis генерирует проверки сам), а контрактные тесты ловят расхождение «мок против реальности» — связка с testcontainers из статьи про интеграционные тесты.

Примеры в спеке: недооценённая половина пользы

Поля examples у схем и операций — то, что делает спеку живой: мок-сервер отвечает именно ими, документация (Swagger UI/Redoc) показывает реалистичные тела, генераторы тестов берут их как базовые кейсы. Правило команды: PR, добавляющий эндпоинт без примеров запроса и ответа (включая ошибку), возвращается на доработку. Стоимость — пять минут, выигрыш — каждый потребитель экономит часы на «а что там реально приходит».

Организация работы двух сторон

Конкретный ритм, который работает: (1) черновик спеки пишет автор фичи (чаще бэкенд) за час до реализации; (2) получасовое ревью с фронтендом — правки в спеку дешевле правок в код в разы; (3) merge спеки — обе стороны стартуют: фронтенд против Prism-мока, бэкенд против сгенерированных интерфейсов; (4) интеграция — прогон контрактных тестов; (5) расхождения чинятся в спеку первым делом, код подгоняется следом. Для внешнего API к схеме добавляется публичная документация (Redoc из той же спеки) и песочница; локальные инструменты проверки — curl/Postman из статьи про тестирование API.

Схемы и переиспользование: где спека становится удобной

Разница между спекой, которую читают, и спекой, которую избегают, — в организации схем. Правила, которые работают: каждая сущность домена описана один раз в components/schemas и используется по $ref везде (дублирование схем расходится в первую же правку); ответы обёрнуты в единый конверт ошибки (error: {code, message, details}) — потребители пишут один обработчик вместо десятка; пагинация, сортировка и фильтры оформлены переиспользуемыми параметрами, а не изобретаются в каждом эндпоинте. Отдельная дисциплина — nullable/обязательность полей: «поле иногда отсутствует» и «поле иногда null» — разные контракты, и путаница между ними — источник половины интеграционных багов.

Полезный приём для эволюции API — версионирование через дефолты: новые поля добавляются опциональными, потребители мигрируют в своём темпе, удаление полей — только в новой мажорной версии с периодом параллельной жизни обеих. Спека при этом остаётся единой: параллельные версии живут в servers/префиксах путей, а не в двух расходющихся файлах. Такой подход превращает контракт из «момента согласования» в живой инструмент развития API — именно в этом его долгосрочная ценность, а не в первичной разблокировке фронтенда.

FAQ

Не слишком ли это тяжело для маленькой команды? Порог — один файл и линтер. Тяжесть появляется при попытке внедрить «полный процесс» сразу; начните со спеки + моков для новых фич и не трогайте легаси до боли.

Что делать с существующим API без спеки? Сгенерируйте черновик из кода (code-first инструменты), вычистите и зафиксируйте как контракт; с этого момента изменения — через PR в спеку.

GraphQL отменяет OpenAPI? Это разные инструменты: для REST-сервисов OpenAPI — стандарт; GraphQL живёт своей схемой. Внутри продукта могут соседствовать оба.

Кто владеет спекой? Владелец — команда сервиса, но изменения, затрагивающие потребителей, — только с их ревью. Технически это CODEOWNERS на файл контракта плюс договорённость о ломающих изменениях.

Где хранить спеку: с кодом или отдельно? Для одного сервиса — рядом с кодом: контракт меняется тем же PR, что реализация. Отдельный репозиторий контрактов оправдан, когда потребителей много и они не хотят тянуть чужой код; цена — процесс синхронизации версий.

Что делать, если реализация и спека разошлись? Чинить в спеку первой и подтягивать код, а не наоборот: спека — контракт с потребителями, её «тихая» правка задним числом ломает их доверие. Профилактика расхождений — валидация ответов тестами и diff-проверка в CI.

Источники: спецификация OpenAPI, openapi-generator, swagger.io (ссылки в шапке).