Pull to refresh

Comments 4

Новичкам будет намного легче понимать сваггер, если вместо "автоматическая генерация документации" начнут говорить "конвертирование комментариев в коде в документацию".

Сейчас преподносится некая магия, когда вроде настроил конфиг скриптов и на выходе получил красивые странички с документацией. Которая ещё и сама "магически" обновляется.

Но по факту, если разработчик обновил код, но не обновил комментарии к нему, магия пропадает.

Ещё сложнее осознавать, что "язык" комментариев не одинаков: где-то "* @returns {ApiError.model} default - Ошибка запроса",
а где-то "// @Failure 500 {object} httpModel.ResponseMessage"

Добрый день.

Да, Вы правы. Формулировка "конвертирование комментариев в коде в документацию" была бы более понятна новичкам, однако я посчитал что мой посыл понятен, так как этим комментариям я уделяю большое внимание (особенно проекту с кодовым названием NEJ).

Также в статье я описываю, что необходимо для генерации документации по комментариям выполнять определённую команду (они разные для обоих проектов). Эта команда является в своём роде "чёрным ящиком". Но в статье я и не преследовал раскрыть более подробно функционал генерации, каким образом происходит генерация, не затрагивал алгоритмы и не опускался на нижние уровни предоставляемой абстракции.

Из статьи можно сделать выводы о том, что для разных технологических стеков есть разные пакеты, которые облегчают генерацию документации Swagger по коду. На стеке Node.js, Express.js, JavaScript (NEJ) - это многострочные комментарии, а на стеке Golang, Gin (GG) - это однострочные комментарии. Я также делаю акцент на их разнице.

На счёт "магия пропадает" могу сказать следующее. Я не просто так упоминал в статье архитектурный паттерн Controller Service Repository. Дело в том, что в большинстве случаев при документировании API через Swagger комментируют именно самый верхний слой - контроллеров. В статье я рассказываю о том, что в проекте с Express.js этот слой выделяется в Controllers, но по факту комментарии пишутся в routers, т.к. именно там идёт связывание маршрутов с методами контроллера. Например, для NEJ это выглядит следующим образом:

/**
 * Авторизация пользователя
 * @route POST /auth/sign-in
 * @group Авторизация (пользователь) - Функции для авторизации пользователя
 * @param {SignInDto.model} input.body.required Входные данные
 * @returns {AuthDto.model} 200 - Авторизационные данные пользователя
 * @returns {ApiError.model} default - Ошибка запроса
 */
router.post(
    AuthRoute.signIn,
    [
        check('email', 'Введите корректный email').isEmail(),
        check('password', 'Минимальная длина пароля должна быть 6 символов')
            .isLength({ min: 6 }),
        check('password', 'Максимальная длина пароля равна 30 символам')
            .isLength({ max: 30 })
    ],
    authController.signIn
);

От их расположения в NEJ мало что зависит, важно чтобы в options были прописаны к ним пути.

Однако, к чему я это. В самый верхний слой редко требуется внесение каких-либо правок. По сути это модель "чёрного ящика" - какая-то информация входит в него, а какая-то выходит и это всё что мы знаем. Это происходит благодаря чёткому разделению ответственности между слоями (про SOLID я также упомянул, хоть и косвенно). А потому достаточно определить входные и выходные данные. Как там внутри бизнес-логика будет реализована - нас мало интересует, мы не преследуем цель документирования бизнес-логики, документирование API и бизнес-логики - разные вещи, а последняя как раз часто и меняется, что может выливаться в историю "наш код не имеет ничего общего с документацией".

Достаточно лишь обновлять комментарии в верхних слоях, определять входные и выходные данные, описание, группировку и другое что потребуется при документировании API.

Статья рассчитана не на новичков, я этот факт подчеркнул меткой сложности как "средней".

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

а ещё у вас в коде (меня только гошный интересует) оч много антипатернов. Вы судя по всему забили на чистую архитектуру и некоторые 12 factor apps, логи в стдаут например. Поэтому выглядит гошная часть не очень

Добрый день.

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

REST API можно реализовать на чём угодно: Gin, Nest.js, Node.js, Django, Laravel, Flask, Spring Boot и так далее - всё зависит от тех самых "многих факторов", на которые я ссылаюсь выше. И документирование API сервиса (или приложения) можно разными способами. Можно действительно писать громоздкие комментарии, точно следуя стандарту Open API, проверяя при этом каждую модель и за счёт этого увеличивать размеры файлов до очень огромных масштабов. Если Вы описывали API с помощью стандартных средств (просто в комментариях используя официальную спецификацию Open API), то, думаю, Вы понимаете о чём идёт речь. Можно даже посмотреть как выглядят эти громоздкие схемы (а их нужно описывать ещё и в комментариях к коду).

В статье же разбираются инструменты, с помощью которых можно облегчить процесс документирования не используя в комментариях к API стандарт Open API, а использовать удобный синтаксис аналогичный JSDoc (для Go исключение - там не используются многострочные комментарии для описания работы конкретного API), с помощью которого и генерируется документация по спецификации Open API. На мой взгляд именно использование swaggo в значительной степени облегчает документирование кода REST API сервисов.

В добавок, можно оценить go-swagger и swaggo по "звёздочкам" на GitHub, если учесть что эти "звёздочки" определяют полезность и популярность какой-либо зависимости для разработчиков. Если взглянуть на go-swagger, то звёзд там порядка 8.7k, а при просмотре swaggo можно отметить что звёзд там 8.3k. На момент 03.06.2023 разница не велика, а значит обе зависимости были оценены обществом разработчиков как "достаточно полезные". Впрочем, можно тему с оценками развивать и далее, употребив здесь различные контексты и метрики, но пожалуй остановлюсь на этом.

В комментарии Вы отметили, что в коде демонстрационного проекта написанного на Go "оч много антипаттернов", можете привести эти антипаттерны? Сама оценка "очень много" говорит о том, что их там намного больше чем один или даже три. В зависимости от того, что Вы подразумевали под "оч много".

Также, я считаю что демонстрационный проект поддерживает чистую архитектуру. В проекте реализован паттерн Controller Service Repository, с полным соответствием SOLID, местами есть упрощения, но какой код их не имеет. Можно взглянуть на структуру и код проекта более детально, чтобы убедиться в этом.

Для вывода логов у меня подключается и конфигурируется отдельный инструмент - logrus. С его помощью я произвожу вывод логов либо в stderr, либо в файл, расположенный в директории logs (в зависимости от того, есть ли доступ к директории logs и созданию в ней файлов для ведения логов). В демонстрационном примере я не уделил его использованию большого внимания, но если глянуть в main.go, то там используется именно данный инструмент, после своей настройки.

Ну и некоторые детали в демонстрационном проекте были скрыты (переменные окружения, некоторые конфигурационные файлы и миграции к базе данных). Их можно увидеть в .gitignore.

В добавок относительно чистой архитектуры пару слов. Она сейчас достаточно популярна, но не есть "таблетка от всех бед". Можно сделать "чистую архитектуру" такой, что потом команда разработки (коллеги) точно "спасибо не скажут". Сейчас она на хайпе, но до этого были популярны другие принципы, подходы и концепции. Не всегда то, что популярно должно быть в каждом проекте. Нужно вдаваться в детали конкретного проекта. И не всегда "забить" - это плохо. Иногда лучше даже "забить".

Sign up to leave a comment.

Articles