DocHub: API по-джентльменски

Kate

Administrator
Команда форума
- Саш, админы говорят, что у нас 400 полетели адово. Глянь, в чем проблема.
- Странно… все же было хорошо.
Пару часов спустя...
- Коллеги, и в очередной раз у нас изменены контракты без согласования и оповещения! Это уже не первый случай! Давайте что-то с этим делать!
Похожий разговор нередко можно услышать в компаниях, применяющих микросервисную архитектуру. Проблема очевидна - большому количеству команд сложно удерживать в актуальном состоянии единое информационное поле. В частности, страдает процесс управления API-контрактами.

Решают проблему различными способами. Предлагаю рассмотреть самые (на мой взгляд) используемые.

Автогенераторы контрактов​

Автогенераторов большой зоопарк. Толковых мало. Например, есть такая тулза для PHP проектов. Обычно сгенерированная документация становится доступна по некому магическому URI после деплоя.

Это решение позволяет надеяться на актуальность документации. Но, имеет ряд недостатков:

  1. Неочевидно, где находится документация. Приходится вести реестр URI контрактов;
  2. Документация требует сборку. Чтобы посмотреть на контракты кому-то, кроме разработчика, требуется задеплоить фичу;
  3. Сложно отследить внесенные изменения в документацию, т.к. она каждый раз перестраивается.
  4. Ну, и самое главное - когда документация появляется на проде, уже поздно. Она конечно окажется актуальной, но выяснить, что именно в ней поменялось, будет проблемой.
В общем, решение заманчиво своей кажущейся простотой, но, к сожалению, в корне не решает проблем.

Contract first​

Концептуально иной подход. Сначала создаются контракты, а затем по ним пишется код. Этот подход сам по себе прекрасен. Вот лишь некоторые профиты:

  1. В процесс дизайна контрактов можно вовлекать несколько команд. Материал оказывается обозримым, т.е. доступен для осознания за разумный промежуток времени;
  2. На этапе продумывания контрактов можно обнаружить логические и архитектурные ошибки. Это позволит существенно сэкономить время на разработку и повысить качество продукта;
  3. Достигнув консенсуса по контракту, команды оказываются в едином информационном поле. Это позволяет одновременно начинать разработку как со стороны поставщика, так и со стороны потребителя.
  4. Для заранее определенных контрактов можно в короткие сроки сделать имитаторы (замокать). Таким образом становится доступно тестирование фич потребителя еще до завершения реализации со стороны поставщика.
  5. Заранее определенные контракты позволяют структурировать деятельность команд и повысить адекватность оценки трудозатрат.
При подходе Contract first, обычно контракты публикуются на портале разработчиков. Например, Confluence. Этот инструмент всем хорош. Он умеет версионировать документы. Фиксирует автора изменений. Умеет уведомлять об изменениях. В общем, устраняется ряд серьезных проблем.

И тут, можно было бы завершать статью, но… есть и ложка дегтя в этой бочке меда:

  1. Толковые инструменты (например, Confluence) стоят денег. Когда речь идет о средней компании, это становится накладно.
  2. Управление документацией - отдельный процесс. Он разорван с процессом написания кода. Если при реализации выясняется объективная необходимость внести изменения в контракт, это требует заметных усилий.
  3. Документ, описывающий контракты, не статичен. Он развивается. Взяв в работу документ, разработчик постоянно задает себе вопрос: "Что тут опять поменяли?". Сравнить две версии документов даже в Confluence проблема. Дело в том, что, например, Swagger-нотации не поддерживаются Confluence из коробки. Для их просмотра нужен плагин. А контент плагина сравнивать уже "больно".

Контракты как код​

Стратегически мы (Работа.ру) движемся к ArchOps. Это как DevOps, только про архитекторов. Гуглить на эту тему бесперспективное занятие. В будущем, я детальнее опишу куда мы уже дошли и куда стремимся. Уверен, тема заслуживает внимания. Но, для данной статьи достаточно простого манифеста ArchOps - Архитектура как код.

Выражается это в управлении архитектурными артефактами как кодовой базой. Например, описать схему можно не в MS Visio или Draw.io, а кодом PlantUML. Артефакты хранятся в репозиториях и подчиняются установленному в компании порядку работы с ними.

DocHub это один из инструментов реализующий подход ArchOps. Он рендерит контракты непосредственно из репозиториев.

d92908642ead3bf56e3c35b0665bd689.png

Акцентирую внимание, что контракты размещаются непосредственно в кодовой базе проекта. То есть любой, кто имеет доступ к кодовой базе проекта, может вносить изменения в них. При этом, контракты являются частью процесса разработки и принимают участие в code review.

Флоу выглядит примерно так:

4dea28f8f3651f49c61f7a2a53286b14.png

Флоу разделено на два этапа:

  1. Developing target API - тут развиваются целевые контракты. То есть, те контракты, которые мы должны реализовать в будущем. Артефактом данного этапа является файл TargetAPI.yaml. Разумно этот этап делегировать архитектору или аналитику;
  2. Developing feature - здесь разработчик реализует фичу по заранее подготовленным целевым контрактам. Результат своей работы он фиксирует в артефакте ActualAPI.yaml.
Отдельно, подробно нужно рассмотреть необходимость двух артефактов:

  1. TargetAPI.yaml - артефакт подхода Contract first. Если нужно реализовать очередную бизнес-фичу, от ветки develop отщипывается ветка для развития целевых контрактов. В ней в файл вносятся необходимые изменения. Затем делается пул-реквест в ветку develop и в качестве ревьюверов назначаются заинтересованные члены команды. Этот файл всегда будет опережать фактическую реализацию. Это проблема.
  2. ActualAPI.yaml - развивается разработчиком по мере реализации кода. Разработчик переносит из целевых контрактов те, которые фактически им реализованы. Это позволяет накапливать в develop полный перечень фактически реализованных контрактов. Тем самым решается проблема описанная в п.1
Профиты такого подхода:

  1. Развитие документации идет независимо и по понятным принципам;
  2. Изменения и история наглядны и доступны;
  3. Контроль документации встроен в процесс разработки;
  4. На документацию можно навесить pipeline который будет извещать заинтересованных о планах изменений в контрактах. Да, и много чего еще.
Но… как всегда есть и проблемы:

  1. Все так же не ясно где искать документацию;
  2. Неудобно “читать” контракты.
Именно эти две проблемы решает DocHub. Он позволяет агрегировать все контракты на одном ресурсе, а встроенный Swagger UI рендерит контракты непосредственно из GitLab.

Архитектура DocHub​

DocHub глубоко интегрирован с GitLab. По сути DocHub это SPA приложение, а GitLab для него backend. Авторизация, в том числе, происходит через GitLab.

8396617e0d83442db78c89606e0ea2fb.png

Агрегация контрактов реализована предельно просто. В каждом репозитории размещен манифест dochub.json. В нем указаны ссылки на контракты данного сервиса. DocHub проходит по репозиториям и собирает манифесты. На их основании он строит навигационное дерево. Примерно так:

8335a2ef62d98d9d322464e43e47dbf7.png

Узнает он о необходимых для сканирования репозиториях из корневого манифеста. Его размещение указывается явно в настройках приложения.

Обратите внимание, что помимо рендера контрактов из GitLab, DocHub позволяет подключать внешние ресурсы по http/https. Это удобно в случае интеграции с внешними сервисами, публикующими свои контракты в нотациях Swagger. Все в одном месте.

Манифест DocHub​

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

Расположение корневого манифеста указывается в настройках приложения (src/config.json).

Пример корневого манифеста (/dochub.json):

{
"imports": [ // Определяет подключаемые проекты (манифесты).
// Файл манифеста всегда должен иметь название dochub.json
// и располагаться в корне репозитория.
{
"project_id": 106, // Идентификатор проекта в GitLab
"branch": "develop" // Ветка в которой расположен актуальный манифест проекта
}
]
}
Пример манифеста проекта (/dochub.json):

{
"docs": { // Перечисляются контракты проекта
"sbs-targetapi": { // Уникальный идентификатор документа
"icon": "lightbulb_outline", // Доступные иконки тут - https://materialdesignicons.com/
"location": "Sberservice/Backend/Целевой API", // Расположение в навигационном дереве
"description": "Целевой REST-интерфейс для бэка", // Краткое описание
"transport" : "gitlab", // Контракт расположен в GitLab
"project_id": 106, // Идентификатор проекта в GitLab
"branch": "develop", // Бранч в котором расположена актуальный контракт
"source": "app/Core/Docs/TargetAPI.yaml" // Описание контракта в нотации Swagger
},
"sbs-realapi": {
"icon": "lightbulb_outline",
"location": "Sberservice/Backend/Фактический API",
"description": "Фактический REST-интерфейс для бэка",
"transport" : "http", // Контракт расположен на внешнем ресурсе и доступен по http
"source": "https://foo.site/api/v1/docs/api-docs.json"
}
}
}
  • Корневой манифест может содержать блок docs, но рекомендуется избегать этого. Нарушается принцип автономности проектных команд по развитию документации.
  • Подключаемые манифесты могут включать в себя блок imports, таким образом, подключая другие манифесты.
Одной из ключевых фич DocHub является сравнение контрактов, остановлюсь на ней подробнее.

Сравнение контрактов​

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

6e6e5e6e92d313916ea034efe067ee0e.png

DocHub умеет сравнивать как построчно (текст), так и по сути. На картинке наглядно видно контракты, которые подверглись изменениям.

Заключение​

Мы используем DocHub уже более года. Инструмент прижился. Есть амбициозные планы по его развитию. Предполагается использовать его для рендера артефактов ArchOps.

Мы надеемся, что инструмент будет полезен и вам. Вы можете смело использовать его в рамках лицензии GNU GPL v.2 Open source license. Будем признательны за ваш вклад в его развитие. Ну и конечно - мы открыты к идеям!

Проект​

https://github.com/RabotaRu/DocHub

Источник статьи: https://habr.com/ru/company/rabota/blog/561836/
 
Сверху