Комментарии 13
Мне вот всегда было интересно, чем же руководствуются те, что генерируют спецификацию из кода? Ведь спецификация есть нечто иное, как контракт для взаимодействия между системами, т.е. она должна являться источником истины, а не наоборот.
В реальном мире это можно представить как взаимоотношение, например, клиента и банка. Условия, на которых банк оказываем услуги (не обнуляет ваши счета, начисляет проценты по вкладам и так далее) зависели бы от того, как банк фактически обходится с вашими средствами, а не от того, на каких условиях вы заключили с ним контракт (договор, условия обслуживая и т.п.).
Борис, вы безусловно большой молодец, что разобрались со своим кейсом и поделились опытом! Но мне вот просто интересно - почему бы не описать спецификацию в yaml/json формате, и из неё уже сгенерировать код под Echo сервер используя, например, deepmap/oapi-codegen? Вносить изменения будет так же просто - изменили спеку (контракт), сгенерировали соответствующий код, поправили имплементацию. Но правило источника истины в этом случае сохраняется, и бережёт вас же от обратно-несовместимых изменений, и значительно упрощает ревью. Да и кода будет меньше, и поддерживать 3rd party решение вам не придётся.
Условия, на которых банк оказываем услуги (не обнуляет ваши счета, начисляет проценты по вкладам и так далее) зависели бы от того, как банк фактически обходится с вашими средствами, а не от того, на каких условиях вы заключили с ним контракт (договор, условия обслуживая и т.п.).
Как будто в жизни так не бывает? У меня летом в банке сняли 30 дополнительных $ за swift перевод просто потому, что у них в зависимостях имплементации что-то поменялось.
Мне кажется, мы как раз про разные подходы говорим, и ни один из них не лучше или хуже другого. Следовать строго оговоренное документации заранее приятно и удобно. И главное, что можно доверять друг другу, договорившись на берегу.
Но бывают случаи, когда нужно строить документацию на основании того, что получилось на выходе из разработки. Когда ты написал северную часть, сразу же показал фронту, он пошел на основании этого реализовывать свое. И любые изменения он тоже может отследить.
Правильный комментарий ниже, что это может быть моя травма от python. Но раз там так носят, значит и в Go можно. Кроме того, приведенные мной библиотеки в примерах имеющихся реализаций способны строить аннотацию по коду. Но делают это не самым удобным для меня способом
>До разработки на Go я много писал проектов на Django и FastAPI.
Это объясняет то что вы хотите использовать свагер не правильно. Не хочу обидить питон разработчиков - я сам в каком-то смысле питон разработчик, но в питоне в силу динамической типизации плохо работает вариант "генерировать код из свагера".
В го надо делать строго наоборот - писать свагер и из него генерировать и код и сервер. Причем рекомендую ogen (реклама его уже была на хабре) вместо oapi-codegen. Попробуйте и поймете абсолютно другой уровень комфорта.
Возможность сгенерировать Swagger не отменяет подход, когда Swagger пишется вначале руками (API-first approach). В процессе разработки вы можете использовать сгенерированное описание для проверки соответствия реализации исходной спецификации.
А это не зона ли ответственности E2E тестов, разве?
Скорее зона ответственности unit тестов. Но везде есть человека человеческий фактор. Спецификация, swagger, не должна меняться, если при реализации допустили ошибку. А она может измениться, поэтому swagger не должен меняться при измерении кода.
Это называется Schema-based Contact Testing. Подход находится выше юнит тестов потому, что использует данные снаружи. Но ниже E2E - их можно выполнять в изоляции локально или на CI - без развертывания приложения и его зависимостей. Удобно, когда у вас много микросервисов со своими релизными циклами и развертывание всего стека в рамках CI невозможно или нецелесообразно. По смыслу это близко к статистикой проверке типов, где Swagger (OpenAPI, AsyncAPI) вступают в роли унифицированной (платформонезависимой) нотации описания интерфейсов.
Я в своих идеях отталкивался как раз от необходимости строить доку на основании того, что получилось на выходе из разработки. Мне понравилось генерировать код для grpc, но все же при возможности я хотел бы писать структуры сам, сладить, что в них поменялось на выходе, в нужных местах заполнять поля. А не так, что "вот мы тебе сделали, теперь пойди угадай, что же поменялось и везде где надо поиспользуй поля". Может это мой пиьонячий подход играет
Смотрите - подход со swagger-first в небольших проектах часто неудобен. Если разработчик fullstack тоже.
swagger-first на бекенде
- добавляем файл swagger
- добавляем в зависимость утилиту генерации бекенда
- следим чтобы генерация соответствовала файлу и периодически генерим начисто
- вместо написания кода на языке бекенда - пишем сначала свагер (+1 языковая технология в стек проекта)
backend-first на бекенде
- добавляем код публикации свагера и все, работаем как обычно
Пока сборка проекта и среды разработки не будут поддерживать swagger как часть кода, второй вариант будут принимать часто как наиболее удобный и простой в поддержке. Если подключенный swagger даст в проекте автоматически вложенные в него модели (как фейковые классы по аналогии как сделаны в android элементы activity) и примапит хендлеры по какому-то правилу, тогда скорее всего повсеместно откажутся от генерации из кода
Так не пройдет, когда из сваггера еще фронт на тайпскрипте генерируется. А это намного удобнее, чем фронтам постоянно под изменяющийсщ сваггер подстраиваться
Я про бекенд - на фронтенде все в обоих вариантах одинаково, там без утилит не обойтись в любом случае. Ну и в нормальных местах бекендеры не ломают API от нефиг делать - на ревью и проектировании обязаны следить за совместимостью
Нет, не одинаково. Потому что мы готовим сваггер файл отдельным пулл реквестом, одобряем его со стороны фронта и продакт менеджера, мержим его в мастер. И потом и бек и фронт работают отдельно на основе уже одобренного контракта. Для фронта оставшаяся интеграция — это где-то 10% работы после завершения бека.
Генерация Swagger для сервера Echo