Расскажу об интересной штуке под названием RAML. Использую в текущем проекте и очень доволен. Технология молодая, информации в сети мало, на русском вообще не попадалось.

Предположим, несколько сервисов сообщаются по HTTP API. Авторизация, история операций, бизнес-транзакции. Сервисы принимают и отдают JSON, сигнализируют об ошибках правильными статусами ответа. Нет пользователя – 404, нет прав – 403, кривые данные – 400. Классический рест.

Как составить документацию? Нужно перечислить все урлы. Указать правила авторизации, заголовки, как правильно их составить. Для каждого урла перечислить методы GET, POST, etc. Описать структуру входных данных. Структуру ошибочных ответов. Добавить человеческое описание каждого метода. И все это поддерживать в актуальном состоянии.

Возможно, есть специалисты, которые ведут документацию правильно, чтобы все было описано по пунктам и ничего не расползалось. Не нужно уточнять детали, ответ сервера в точности такой, как написано. И группа людей соблюдает все соглашения о ведении документации.

На практике я вижу обратное. Документация отстает от разработки. Текст пишут в вики в ужасной разметке. Каждый человек придерживается особых правил. На ретроспективе холиварят о том, как документировать правильно.

RAML решает эти проблемы. Название означает REST API Markup Language. Технически это YAML-документ с набором фич. Стандарт задает жесткую структуру для описания рестовых апих. Разработчики держат этот файл в гите и наполняют вместе с кодом. Во время билда особая утилита переводит документ в формат HTML.

Перечислю достоинста технологии:

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

  2. Формат YAML. Это лучший формат для конфигураций. Краток, удобен для чтения. Поддерживает основные типы. Имеет списки, словари. Поддерживает многострочные данные. Разрешает комментарии. Не падает из-за лишней запятой на конце, как JSON.

  3. Поддержка markdown. Описание к каждой сущности пишется в маркдауне. Это самый простой язык разметки. Очень подходит для вставки кода, простейшей структуры (заголовки, подзаголовки).

  4. Инклуды. Большой файл легко декомпозировать на составные части и подключать по частям директивой include. Более того, инклуд поощрается стандартом, чтобы не дублировать сущности. Например, любой list-метод (список сущностей методом GET) принимает параметры limit и offset. Создаем отдельный файл с их описанием, примерами. Подключаем к нужным методам инклуд, компилируем. На выходе у каждого метода идентичное описание этих параметров.

    Инклуды позволяют комбинировать документацию для разных целей. Например, есть публичные апи, а есть внутренние. Описываем каждую в отдельном файле. Создаем два документа. Первый для заказчика, с инклудами только публичных апих. Второй для внутренних нужд – только с инклудами внутренних.

  5. Утилиты и экспорт. Документацию в RAML легко обрабатывать машинным способом, потому что это стандарт, протокол. Уже существует пачка утилит для работы с форматом. Визуальные редакторы, генерация кода по заданным урлам, плагины к редакторам и ИДЕ, и конечно, тулза для экспорта в markdown и HTML.

  6. JSON-схемы. Схема – лучший способ описать структуру данных. Она заменит долгие списки и абзацы человеческого языка. Схема декларативна – сложные структуры могут быть представлены как ссылки на схемы проще. RAML поддерживает инклуд схем.

  7. Поддержка HTTP/REST. Стандарт знает все о заголовках и статусах ответа. Красиво, когда документация покажет не только тело ответа, но и статус с описанием, примеры заголовков.

Существует два версии формата: 0.8 и 1.0. Вторая предлагает больше полей и возможностей для описания. Я пока что пользуюсь 0.8.

Рассмотрим простой пример. Пусть есть простая апиха. Вот что мы напишем в заголовке файла example.raml:

#%RAML 0.8
title: Some Title
version: v3
baseUri: https://example.com/api/v1/

Добавим вводную документацию. Для каждого раздела укажем подзаголовок. Ниже:

documentation:
 - title: Main Title
   content: |
     common notes on this document.

 - title: Authorization
   content: |
     Some text to describe HTTP headers to access data.
     ~~~
     code goes here...
     ~~~

Задекларируем правила авторизации. У нас в проекте это обычная базовая авторизация по протоколу HTTPS. Стандарт RAML знает, что это такое:

securitySchemes:
  - Basic Authentication:
      type: Basic Authentication

Теперь, описывая урл, можем просто состаться на этот тип авторизации. В скомпилированном HTML-документе напротив урла будет стоять замочек, а по клику откроется окошко с описанием правил авторизации.

Начнем описывать урлы:

/api/v1/user:
  securedBy: [Basic Authentication]
  get:
    description: |
      Retrieves a list of users.
      ### Syntax
      ~~~
      GET /api/v1/user/
      Host: {host}
      Authorization: {authorization}
      ~~~
    queryParameters:
      !include user_list_params.raml
    responses:
      200:
        body:
          application/json:
            example: !include examples/user_list_response.json
            schema: !include schemas/user_list_response.json

Все просто. Мы декларируем апиху, которая отдает список юзеров. Доступ защищен базовой авторизацией. В описании пример запроса. Файл user_list_params.raml содержит парамеры командной строки: лимит, смещение, сортировка.

Схема ответа может быть большой, поэтому инклуд. В файле examples/user_list_response.json лежит схема, примерно такая:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "additionalProperties": false,
    "definitions": {
        "item": {
            "additionalProperties": false,
            "properties": {
                "id": {
                    "minimum": 0,
                    "type": "integer"
                },
                "name": {
                    "maxLength": 64,
                    "type": "string"
                }
            },
            "required": [
                "id",
                "name"
            ],
            "type": "object"
        }
    },
    "properties": {
        "count": {
            "minimum": 0,
            "type": "integer"
        },
        "results": {
            "items": {
                "$ref": "#/definitions/item"
            },
            "type": "array"
        }
    },
    "required": [
        "count",
        "results"
    ],
    "type": "object"
}

Смотрите, как удобно: в начале схемы декларируется тип юзера. Конечный ответ – это массив таких сущностей.

Дальше документ очень удобно развивать. Добавлять методы (POST, PUT, DELETE), ссылаться на уже определенные структуры, выносить повторы в инклуды.

Скомпилируем документ в файл. Утилита raml2html написана на node.js и ставиться через npm. Компилим:

raml2html example.raml > example.html

Не нравится дефолтный шаблон? Можно передать свой:

raml2html -t custom-templates/template.nunjucks -i example.raml -o example.html

В результате получим HTML-документ (UPD документ по ссылке удалили).

RAML действительно экономит время на составление документации. Технология молода, но очень перспективна. Советую использовать уже сейчас.