Pull to refresh

Comments 16

использовал в практике https://github.com/oapi-codegen/oapi-codegen/ и как раз четко под задачу.

Комплексно слишком он ограниченный и множество мест руками надо делать. Но если вам надо openapi-first что бы документация была 100% валидной то тогда он ваш выбор. Плюс в нашей задаче была повышенная безопасность и потому сверху без проблем допились свои фильтры, что позволило собирать бинарник для клиента где все вшито и мы были уверены что клиент никак его не запустит и не подключит, что бы было небезопасно в первую очередь для клиента.

из минусов те самые ограничения - только openapi и то не прям весь, валидаторы один хрен самим писать и тесты к ним нормально, нет вебсокетов (но это известная проблема openapi в первую очередь) и сложности если апи отдает что то более чем json/xml

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

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

Насчёт одного из минусов: для валидаций можно прописывать прямо в OpenAPI спецификации тэг "x-oapi-codegen-extra-tags", в котором прописывать тэг validate, который генерируется и затем обрабатывается пакетом go-playground/validator. Пример: [https://blog.commitsmart.com/go-oapi-codegen-request-validation-285398b37dc8]. Просто если бы я рассказывал об этом в статье, она бы превратилась из лонгрида в лонг-лонгрид, показать на примере ozzo-validation с более понятной логикой мне показалось более наглядным и простым)

мы иначе валидацию реализовали)
так как все есть объект и openapi является и конструктор в том числе как protobuf при генерации, мы просто привязались к этим структурам

то есть в самой документации мы Х-поле с именем функции -> функция работает со структурой которая генерируется из openapi -> в самом генераторе сделали подстановку валидатора как эту функцию

то есть мы сохранили прозрачность кода и при этом никаких рефлексий, все пробегает при генерации.

нет вебсокетов

Тоже приходилось для описания асинхронных взаимодействий, отдельно поддерживать спецификацию на AsyncAPI.

Ну а если вдруг захотите внедрить это в легаси, моя рекомендация — не пытайтесь переписать все сразу

Я бы сперва в обратную сторону сгенерил OpenAPI-спецификацию из легаси (многие фреймворки умеют это из коробки), а потом доработал и на основе неё реализовал бы уже spec-driven подход.

Я согласен: если OpenAPI спецификации вообще нет, сгенерировать первую, "черновую" версию из кода - отличный ход!

Спасибо! Разделяю этот подход, а для тех, кто страдает и пишет опенапи руками - рекомендую TypeSpec. Из него же можно и клиенты накодогенерить

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

Когда кодогенерация гарантированно решает многие проблемы. Раньше в пыхе использовал openapi-codegen и все сразу же заиграло новыми красками, щас в go также перешел на openapi-codegen и просто кайф. Никакой ИИ не сравнится с полученым результатом. На выходе с кодогенерацией мы имеем гарантии, строгую типизацию, валидацию, хендлеры, тесты все из коробки.

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

А опенсорс кодогенератор перепроверять не надо. Там же не бывает ошибок никогда.

При повторной кодогенерации все ручные изменения стерутся ?
опасненько так жить если всё стерётся...

Если нужно какие-то методы, например, дописать - это можно сделать в отдельном файле. А если хочется сгенерированный код переписывать, то это плохая идея (даже IDE об этом предупредит), ибо при повторной генерации изменения пропадут. Лучше изменить шаблон, тогда результат генерации будет воспроизводимым. Этого мы, в том числе, хотим, вводя spec-first подход.

у вас указано, что есть еще protobuf для grpc. Как вы в таком случае синхронизируете контракт между openapi и protobuf и гарантируете совместимость?

я такую же проблему решал, но с другой стороны. нужно было с grpc переходить на http, решил сохранить proto файлы и поверх них написать генератор.

Кажется такой подход чуть лучше работает:

  • общий контракт для gprc и http

  • правила валидации можно в том же proto прописать

  • openapi можно из proto генерировать

Моя команда генерации так выгядит:

--go_out=paths=source_relative:. - структуры го

--go-grpc_out=paths=source_relative:. - grpc обертка

--validate_out=lang=go,paths=source_relative:. - валидатор (envoyproxy/protoc-gen-validate)

--openapi_out=output_mode=source_relative:. openapi(google/gnostic)

--httpgo_out=paths=source_relative:. http server+client (моё решение https://github.com/MUlt1mate/protoc-gen-httpgo)

Со случаями синхронизации openapi и protobuf не сталкивался, спасибо Вам, что поделились таким интересным опытом! А вот переводить легаси-сервис с http на grpc приходилось, но синхронизация там не требовалась: сервис был полностью доделан. Просто на серваке сначала сделал grpc+http, потом перевел сервисы-клиенты на grpc, затем выпилил http-сервер. Для «чернового» перевода одного в другое сервисов и утилит нашел предостаточно, это радует

Protobuf я упомянул лишь по той причине, что показывал, как у нас устроен репозиторий контрактов, в котором мы храним и генерируем не только openapi, но ещё и proto с cloudevents. Ну и потому, что он изначально с рассчётом на Documentation-Driven разработку создавался

Так ваш протобаф гошный может сразу и в хттп и в грпс.

Я Думал все гоферы с молоком матери начинаюь сначала протобаф описывать, а потом проток генерейть и готов хендлер какой хошь. Проток мок и вот тебе заглушки товарищь фронтендер.

Апи фесту уже 1000 лет в обед.

А SDD - спекулянтус дривнус девелопментус - это шкодерам жизнь проделвает. Написал спеку для ллм. А она тебе пофиг какой код, главное чтоб лампочками моргал)

Компилятор первым сообщает, что именно надо поправить в реализации.

Причём тут компилятор? У вас там panic() — это runtime.

То есть чтобы всё это отловить - всё api должно быть покрыто тестами. А их как вы автогенерите?

Тут имелось в виду: когда мы изменили сигнатуру в спецификации и перегенерировали код, IDE, а затем и компилятор Go выдадут ошибку (несоответствия нашей реализации сервера сгенерированному интерфейсу сервера) на строке с вызовом функции RegisterHandlers.

Компилятор тут при том, что один из этапов компиляции — Type-checking and AST transformations (cmd/compile/internal/gc) — тут происходит магия по авто-типизации, проверка интерфейсов, определение мертвого кода и escape-анализ

Sign up to leave a comment.

Information

Website
www.mts.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия