Генерация контрактов OpenApi или прикладной API first: совсем немного про зачем
Здесь я писал о том как настроить генерацию. Теперь немного предыстории.
Новое место, новая позиция, новый продукт! Финтех, камунда, ~ 40 (!) микросервисов за которые отвечает наша команда. Первый спринт. Я в роли наблюдателя. В спринте вроде бы обычная задача — нужно вызвать из одного сервиса другой, и обработать результат. Ребята оценивают, начинают работу, и что я вижу в течение следующих дней: один разработчик берёт сервис-сервер, другой сервис-клиент, и каждый начинает реализацию контракта описанного в табличке в confluence. Что-от около десятка полей. Они уходят на пару дней, возвращаются, начинают тестирование контракта, выясняется что одно или два поля немного различаются в названии, уходят править нейминг, возвращаются, тестируют и только после этого переходят к написанию какой-то логики.
И тут меня переклинило. Да, дело не конкретно в этих ребятах или задаче. Или продукте. Или компании. Они просто делают работу как привыкли делать. С точки зрения разработчика — закрыть такую задачу за 3 или 6 дней — нет особой разницы. Над сроками вообще начинаешь заморачиваться только после перехода на роль которая за эти самые сроки хоть как-то отвечает. Но потратить 4 дня силами двух разработчиков только на контрактую обвязку…
Здесь в памяти начали всплывать давние попытки генерации спецификаций по коду. Или документации по коду. Или кода из спецификации. В общем какие-то попытки генерации чего-то связанного с openapi. А дальше мы ушли в углубленное изучение того, как это можно использовать в контексте нашего продукта и большого количества взаимодействий сервисов.
Пропуская этап с экспериментами и выводами, на выходе получилось следующее:
Все наши спецификации лежат в отдельном репозитории. И через ссылки на них генерируются серверы и клиенты. Если нужно доработать контракт сервиса — сперва пишется новая версия спецификации.
Перед там, как начинать работу над новой большой задачей в которой нужно трогать контракты — собираемся на встречу всей командой и пишем черновики спецификаций разных сервисов. На этом этапе аналитики и тестировщики здорово помогают.
Далее с черновиками (эндпоинты и составы полей) разработчики уходят для написания уже красивых и рабочих артефактов.
После этого в сервисах которые мы меняем — подключаются спецификации и генерируется клиентская и серверная части, а далее можно писать саму логику.
Контракты систем с которыми мы взаимодействуем (полтора десятка) — тоже пишем сами. К сожалению, стандартная история — это страничка с описанием в wiki. Реже — openapi спецификация. Поэтому собираем из всего что доступно уже в нашем формате и чтобы работала генерация.
Минусы такого подхода:
Нужно убедить команду попробовать такой подход. (Привычка штука сильная).
Необходимо потратить время на освоение openapi, примеры генерации, инструкции, регламенты.
При необходимости написания хитровыдуманного контракта — можно застрять на освоении anyOf/oneOf/allOf, enum или других интересных вещей.
Плюсы такого подхода:
Время. Если раньше нам нужно было 3 дня и 2 разработчика, чтобы реализовать контракт в сервере и клиенте, то теперь за то же время это сделает один разработчик. И это не говоря про кейсы где нам нужно подключить более одного клиента. Или изменить одно и то же поле, которое путешествует через несколько сервисов.
Всегда есть ссылка на актуальный контракт, который можно отобразить в confluence. И это не адрес на эндпоинт приложения которое развёрнуто где-то там. Или какая-то древняя выгрузка из swagger ui.
Количество ошибок стремится к минимуму. Убираем человеческий фактор при написании кода. А при валидации разными участниками команды полезность артефакта сильно возрастает.
Предсказуемость времени подключения сервера и клиента. Написать спецификацию — несколько часов, подключить генерацию — от десятка минут до часа. Конечно, не включая время ревью и исправлений при необходимости.