Как OpenAPI повлиял на наш системный дизайн

fac7bd753b32901c617bae50b8d2409e.jpegЕлизавета Акманова

Старший аналитик

Всем привет! С вами снова я, Елизавета Акманова, старший аналитик в ГК Юзтех. Сегодня хочу поделиться, почему и как мы с командой discovery перешли на описание API с помощью OpenAPI, и при чём здесь системный дизайн. 

OpenAPI & Swagger

В самом начале хочу разграничить понятия OpenAPI и Swagger. Оба термина взаимозаменяемы, если сильно не придираться. Однако, на текущий момент OpenAPI относится к спецификации формата json/yaml, а Swagger — к семейству инструментов с открытым исходным кодом, которые работают со спецификацией OpenAPI. Swagger представляет собой набор следующих инструментов:  

  • Swagger Editor, в котором мы можем быстро редактировать документацию;

  • Swagger UI, в котором мы можем её отобразить;

  • Swagger Codegen, с помощью которого разработчики могут быстро сгенерировать исходный код из документации.

Вот пример небезызвестного Swagger:  

de22fb768ad12b62dc54e37337efdc7f.png

Если всё то, что находится в headers, после названия версии добавить в адресную строку:

a7dccc608f597d966cf395cab7251845.png

Произойдет открытие OpenAPI, на основании которого сгенерирован Swagger:

cd3b45fb0b1a4b9bffe1dcdfd2f70b24.png

В данном случае это формат json, однако, если вам удобнее работать с yaml, его можно легко получить, заменив в адресной строке .json на .yaml:

d7de2c9cf2272e956c4c60bb761617ea.png

Произойдет скачивание документа на компьютер:

18966b001a4455b868ac3898b77670d6.png

Этот текстовый документ можно открыть в любом текстовом редакторе: Блокнот, Word, Notepad и другие. В нём содержится описание спецификации OpenAPI для того же самого Swagger, но в формате yaml.

a6a618482331c17ede48a95e9ce14a7f.png

Саму структуру файла можно разделить на несколько логических блоков:  

  1. Метаданные
    Этот блок содержит основную информацию о версии OpenAPI, названии, описании. Это помогает пользователям API понять, что они вообще используют:

4bdb07735f3b914dfdbadc44ab0a425b.png

  1. Описание серверов
    Далее идёт описание серверов. Этот блок определяет серверы, на которых размещен API. Это может быть несколько серверов для различных сред:

6c11ce9e1736d788d49f3c83eb9e510e.png

  1. Описание запросов
    Далее самое интересное — сами интерфейсы, запросы. Этот блок описывает пути API и методы, которые они поддерживают. В (скобках) я буду писать номер строки, где это можно найти. В данном примере описан путь (8) /users (9), где поддерживается метод GET (10), позволяющий работать со списком пользователей (11). В качестве ответа (12) мы можем получить статус 200 (13), который содержит как раз список пользователей (14), и ответ (15) содержит в себе json (16) схему (17) из массива (18) сущностей (19) Users (20):

    9f5a0ef9ba13e5a066345a3fdf862cc8.png


    В данном примере ещё не описаны параметры, headers, тело запроса, дабы сэкономить место. Но OpenAPI так же позволяет эту информацию внести.

И назревает актуальный вопрос: где же искать описание сущности Users? Она находится дальше по спецификации.

  1. Описание схем данных
    Этот блок определяет схемы данных, которые используются в API. В данном случае описана схема User, содержащая три свойства: id, name и email. Эти схемы помогают стандартизировать формат данных, передаваемых и принимаемых API:

    ee883439840cc9730584bdb0a2fff098.png


    К каждому параметру можно добавить его свойства: минимальное/максимальное значение, паттерн заполнения (например, в виде регулярного выражения), значение по умолчанию, значения из списка (в виде enum) и многое другое. 

Вот так выглядит один из самых удобных редакторов OpenAPI, его можете найти по ссылке:

0033633d45a21494ebef6c40b6b35004.png

Однако возникает вопрос: кто должен описывать API с помощью OpenAPI? Разработчики, которые используют генераторы OpenAPI? Или аналитики с помощью ручного привода? На моём пути встречались такие разработчики, для которых было мучительно и больно описывать API, поэтому я считаю, что это доля аналитика. Дальше постараюсь обосновать свою точку зрения, но сначала расскажу, как построен процесс работы в нашей команде.

Процесс взаимодействия аналитиков и разработчиков

 У нас всегда при документировании чего-либо есть 2 стороны: разработчики и аналитики. Подход заключается в следующем: аналитиком разрабатывается спецификация и отдаётся на ревью разработчикам. Все изменения, при необходимости, вносятся легко и быстро. Далее, на основе этой спецификации, разработчики своими силами реализуют исходный код, из исходного кода создается сервис, и всё это отдаётся пользователям как продукт. 

Процесс максимально упрощён, чтобы передать общую концепцию!

04977cf3b764347a01dd549a2fcc806c.png

Чего мы таким подходом добились и какие проблемы закрыли:

  1. Внутреннее единообразие
    Каждый аналитик в команде до этого работал в разных проектах, имел разный бэкграунд и свой подход к оформлению требований, в том числе к API. Сначала каждый из нас писал требования по-своему, с разным уровнем проработки и детализации. Это приводило к разночтению требований разработчиками и тормозило реализацию. У нас была проблема: кто-то описывал API в табличном виде, кто-то просто кидал JSON как пример запроса/ответа, кто-то не описывал вообще (да, такое тоже было).

  2. Чёткая структура
    Таким образом, мы пришли внутреннему единообразию: у нас всё связано, всё согласовано и появляется чёткая структура, которой мы следуем. 

  3. Удобная документация
    Данный формат является привычным для разработчиков и тестировщиков.

  4. Точка правды для команд
    Такие документы становятся единой точкой правды, на которую можно ориентироваться. 

  5. Параллельная разработка
    Этот пункт касается не только клиента и сервера, но ещё и автотестов.

  6. Генерировать код из спецификации
    До этого я видела примеры, когда генерируется спецификация из кода (об этом мы ещё поговорим), но при текущем подходе процессы меняются местами. Правда, не каждая команда готова генерировать свой исходный код из спецификации, а не писать его руками, но чисто технически такая возможность есть.

Казалось бы, большинство этих пунктов можно закрыть введением определенного шаблона документа, по которому аналитики бы описывали API. Зачем нарушать зоны ответственности и впускать аналитика в описание методов согласно спецификации OpenAPI? Тем более, можно в разы сэкономить время и сделать то же самое через генератор, а не описывать вручную. Но здесь я готова чуть-чуть поспорить. 

Проблемы, связанные с генераторами OpenAPI-спецификаций

Я сталкивалась с реальными случаями на проектах, когда генераторы OpenAPI расстраивали всех участников команды. Каким образом?  

Этот инструмент нередко содержит ошибки, которые порой не позволяют сгенерировать то, что нужно. Особенно это проявляется в крупных долгоживущих проектах, когда разные части системы, как правило, написаны на разных языках и разных фреймворках. Для каждого из них используется свой генератор OpenAPI, и вероятность того, что один из этих генераторов даст сбой, повышается. Вот пару примеров:  

Внимание, следующий скриншот основан не на реальном проекте, все совпадения случайны!

15ac1dff223412068ad75e343d6ddf57.png

Согласно спецификации, у нас есть два обязательных поля: isActive и store. Однако, если раскрыть их описание, будет сказано, что они опциональные. По аналогичному кейсу, от разработчика получили такой комментарий: «У меня сваггер не удалось победить с дефолтными полями, решил просто писать описание». Костыль? Он самый. 

В практике мы также сталкивались с тем, что у нас не добавлялись в query params все параметры, которые начинались с is… (тот же isActive). Это было более критично, чем пример выше, поэтому разработчик сжёг определенное количество ресурсов и добился успеха. 

Ещё одна из причин: OpenAPI-генераторы способны сгенерировать только часть документации. Но ведь надо ещё добавить подробные описания, примеры использования, примеры сообщений, минимальные и максимальные значения, и всё в этом духе. Это нужно делать вручную и каким-то образом заталкивать в программный код, чтобы потом, на его основе, генератор создал полноценную спецификацию. Решение не из приятных, разработка такое не поддержала. И если раньше наш Swagger выглядел примерно следующим образом:  

10c7c9e9854c441f3ef174a3075a72ed.png

То после внедрения этого подхода стал выглядеть примерно так:   

18e5919e6325351116d3d7041cf18499.png

Такое описание интеграторам отдавать приятнее, так как там собрана исчерпывающая информация про метод. 

И ещё как бонус: может произойти ситуация, когда на проекте используются языки программирования и фреймворки, для которых физически нет генератора OpenAPI-спецификации. Случай достаточно редкий, но имеет место быть. 

Как OpenAPI повлиял на системный дизайн

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

Разработчики смогли сконцентрироваться на написании кода и реализации функциональности, не отвлекаясь на составление и обновление документации, воюя со Swagger. Это позволило нам более эффективно использовать ресурсы команды, повысить производительность и качество кода, а также ускорить сроки реализации проектов.

Плюс ко всему, отдавать такой Swagger, описанный аналитиком, команде интеграторов стало гораздо приятнее, улучшилась коммуникация как внутри команды, так и за её пределами. Кроме обычных системных названий и их типов там появилось его описание, примеры данных, ограничения и все остальные бонусы, которые при интеграции должны быть учтены. 

Рекомендации по внедрению документации в формате OpenAPI

Кроме банальных советов из разряда «учите спецификацию» хочу порекомендовать выполнять следующие действия:  

  1. Сотрудничайте с командой разработки
    Есть риск, что разработка не поддержит такой подход, так как это заходит на их зону ответственности, и получится как в том самом анекдоте:

    babe80cb08548e688ee3f366b160c37d.png


    Постарайтесь аргументированно подойти к этому вопросу и найти в разработчиках поддержку. Определите и установите чёткие роли,   обязанности аналитиков, разработчиков и других заинтересованных сторон, чтобы обеспечить бесперебойный рабочий процесс. Проводите регулярные встречи между аналитиками и разработчиками для обсуждения спецификаций API, устранения неясностей и сбора отзывов.

  2. Внедрите подход API-first
    Это значит, что разработка начинается с проектирования API, а не с написания кода. API становится основой для всей системы. Этот шаг требует изменения мышления, но он приведёт к более структурированному и предсказуемому процессу разработки. 

  3. Внедряйте OpenAPI поэтапно
    Начните с малого: с применения спецификаций OpenAPI к небольшой части проекта или одной конечной точке API. Это позволит вам усовершенствовать свой процесс перед его масштабированием. Используйте обратную связь для итеративного улучшения процесса проектирования API, гарантируя, что он соответствует меняющимся потребностям проекта.

  4. Учите спецификацию
    Тут всё просто: смотрите полный набор функций, который представляет спецификация, и используйте её в необходимом объеме. На текущий момент, здесь можно найти последнюю версию спецификации.

  5. Постоянное улучшение и обратная связь
    Последний, но не менее важный шаг — это постоянное улучшение и сбор обратной связи. Мы должны регулярно собирать отзывы от команды, чтобы понимать, что работает хорошо, а что требует доработки. Это поможет нам адаптировать процесс и инструменты под реальные потребности команды, делая нашу работу еще более эффективной.

Выполнив эти шаги, вы сможете обеспечить беспрепятственное внедрение спецификаций OpenAPI аналитиками вашего проекта, что приведёт к более эффективной и последовательной разработке API.

© Habrahabr.ru