Обновить

Оптимизация без AI: как я автоматизировал API-ручки и типы

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели6.6K
Всего голосов 2: ↑2 и ↓0+4
Комментарии5

Комментарии 5

Добро пожаловать на Хабр.

Идея генерировать апи-клиент с типизацией из openapi стара, и ее недостатки достаточно изучены, чтобы сказать - это скорее нишевая схема, в большинстве проектов добавляет больше неразберихи и проблем, чем пользы.

Часть проблем вы уже нашли сами, с другой частью еще столкнетесь:

  • схема в реальности может расходиться с фактически присланными данными (по моему опыту - частая история), то есть гарантии мы не получаем

  • проблемы с версионированием - если скажем 10 разработчиков бэк+фронт работают над разными ручками в рамках своих задач, нужна сложная инфраструктура чтобы удобно разрабатывать. Это отдельное пространство для проблем, которые можно "героически решать", например публикуя с yaml или с готовым апи-клиентом пакеты во внутренние репозитории, генерируя в день сотни "@api-spec": "123.3.1877-feature-123", синхронизируя со стендами и деплойными циклами, занимаясь сложными слияниями в dev. Ну либо перекидываться в рабочих чатах yaml файлами, а потом на dev стенде после слияния нескольких фич ловить что или фронт или бэк вмерджили что-то не выложенное на стенд или ушли в глубокий конфликт.

  • фронту может быть нужен 1 параметр в конкретной ручке, а бэк присылает 100 (возможно - легаси, или для разных приложений-потребителей). Сгенерированный апи-клиент не очистит лишнее, ему все кажется важным и нужным.

  • в ряде кейсов теряется параллельность разработки бэка и фронта. В задаче согласовали переименование параметра в ручке - фронт не может у себя поменять, проверить, доработать типы и связанный код. Он должен дождаться пока бэк либо сделает задачу, либо сделает заглушки -> генерируется openapi -> генерируется апи-клиент -> можно начинать работу. Либо костылить и реплейсить вручную части сгенерированного апи-клиента.

  • большинство cli-утилит генерации заточены под единый огромный инстанс апи-клиента. Сложно будет сделать lazy loading, разбиение на чанки, модульность (чтобы апи лежало ближе к местам использования), не потеряв единый процесс фетчинга и не наплодив дубляж.

  • велик риск что в апи-клиент попадут неиспользуемые ручки, и в целом анализ по проекту "какие именно ручки и какие именно поля фронт использует" будет затруднен. Бандл неизбежно раздувается, на Хабр летят статьи "почему вкладки браузера тормозят и едят столько памяти".

  • логирование несовпавших ожиданий все равно требуется - то есть необходимо где-то хранить "что именно нужно фронту для работы", и делать дифф со сгенерированным апи-клиентом.

Ну, о недостатках можно говорить очень долго, суть - "сгенерированный апи-клиент по openapi может гарантировать, что он соответствует openapi, но абсолютно не гарантирует что он соответствует конкретному фронту-потребителю".

Конечно, есть кейсы, где это все подходит на каком-то из этапов развития проекта (особенно если количество фронтендеров === 1 и проект маленький), но он скорее тупиковый.

Как не сталкиваться с этими проблемами? Воткнуть генерацию в правильное место - не в то, чтобы создавать js-файл "что примерно отдает бэк", а в то, чтобы "производилась валидация ожиданий между тем, что нужно фронту и что реально отдает бэк". Написать руками DTO для ручек только с теми полями, которые нужны конкретному фронту-потребителю, а дальше уже подключать генерацию, как примерно описывал тут.

Рад быть тут :) Да, сложно не согласиться, что такой подход имеет как свои преимущества, некоторые из которых я описал, так и недостатки в виде сложности с масштабированием и потребности в четком версионировании. Для мелких проектов - я прямо-таки доволен. Спасибо за такой развернутый комментарий о подводных камнях, это ценно

Главное - успейте вовремя остановиться на текущем пути) Если поверх сгенерированного по спеке апи-клиента еще прикручивать автоматические валидаторы типа Zod, то одна из проблем формально решится - то, что бэк реально отдает, начнет валидироваться. Но добавятся новые - фронт будет логировать ошибки или падать при изменении неиспользуемых полей. По факту фронт становится "валидатором, что бэк правильно сгенерировал спеку" - это вообще путь не туда. Я потратил пару лет на этот путь, и продвинулся довольно далеко в энтерпрайзах - но проблемы будут множиться, инфраструктура становиться все сложнее, а по времени и ресурсам бизнесу это все куда дороже, чем даже вручную править.

потратил полдня на то, чтобы понять, почему фронт падает после обновления бэка

Решение этого - не в проверке соответствия бэкенда им же написанной спеке. Просто предостерегаю от излишнего погружения в такую схему - лучше не делать дефолтной для проектов, есть подходы эффективнее.

Спасибо! Это отличный аргумент из практики) На что вы перешли в итоге после того, как пришли к тому, что генерируемый клиент - не тот путь, который вам нужен?

Не понимаю вопрос - в конце первого комментария я описал схему работы и дал ссылку на пример кода.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации