Написание спецификации
Что это такое
Документ спецификации описывает каждый путь, доступные на нём методы, параметры, которые каждый из них принимает, и форму каждого запроса и ответа. Схемы определяются один раз и подключаются по ссылке, поэтому тип, который используется в нескольких местах, описан однажды и остаётся согласованным, а сам документ написан в структурированном формате — его можно проверить, сравнить и отрисовать, а не читать как прозу.
Почему это важно
Самый дешёвый способ найти неоднозначности — описать интерфейс ещё до того, как он построен. Поле, необязательность которого не решена, сбой без указанного кода состояния, параметр, необязательный в одном месте и обязательный в другом: всё это очевидно в схеме и незаметно в коде, пока на это не наткнётся клиент. Документ к тому же становится единственным источником для документации и клиентского кода — и снимает бремя поддержки, из-за которого написанная руками документация API устаревает.
Ключевые идеи
Опишите ресурсы, затем ссылайтесь на схемы
Документ организован по путям и методам, а формы определены в общем разделе и подключаются по имени. Одна и та же схема в запросе и в ответе держит их согласованными, тогда как дублирование формы в обоих местах как раз и заставляет их расходиться. Имена схем должны быть существительными предметной области, чтобы читатель учил словарь по самому документу.
paths: /orders, /orders/{id}
schemas: Order, OrderItem, Error
Описывать нужно каждый ответ, а не только успешный
Спецификация, где перечислен только успешный ответ, оставляет клиенту угадывать форму сбоя. Чтобы клиента можно было сгенерировать с осмысленной обработкой сбоев, нужно описать ответ с ошибкой и переиспользовать общую схему ошибки. Перечисленные коды состояния должны быть теми, которые эндпоинт действительно может выдать.
Обязательность и необязательность должны быть явными, как и допустимость null
Поле может отсутствовать, может присутствовать со значением null или всегда иметь значение — и это три разных контракта, каждый со своим поведением клиента. Схема, где это выражено явно, даёт разницу между клиентом, который обрабатывает отсутствующее поле, и тем, который на нём падает. Заодно приходится решить на стороне сервера, что означает отсутствие.
Параметры несут свои правила валидации
У размера страницы, порядка сортировки, фильтров и идентификаторов есть тип, диапазон и значение по умолчанию. Если описать их в спецификации, валидация проверяется один раз, а клиент генерируется с правильными типами — вместо того чтобы сервер принимал что угодно, а клиент передавал строки.
Спецификация живёт в репозитории и рецензируется как код
Спецификация, которую держат в вики или в инструменте проектирования, расходится с реализацией за считанные недели. Однако верной остаётся та, что лежит рядом с кодом, меняется в том же запросе на слияние, что и поведение, и рецензируется теми же людьми. Дифференциал спецификации — ещё и ясный артефакт ревью: интерфейс изменился, вот как.
Примеры делают документ пригодным к использованию
Реалистичный пример для каждого запроса и ответа сообщает больше, чем одна схема, особенно для вложенных структур и перечислимых значений. Большинство отрисованных документаций показывает примеры первым делом, поэтому слабый пример — плохое первое впечатление об API.
Практика
Опишите один эндпоинт полностью
Возьмите один из имеющихся эндпоинтов и опишите его путь, параметры, тело запроса, успешный ответ и каждый ответ с ошибкой как спецификацию со схемами по ссылкам.
Готово, когда: проверка документа сообщает об отсутствии ошибок, а ответы с ошибкой ссылаются на общую схему ошибки.
Сгенерируйте клиента по документу
Сгенерируйте по спецификации клиента для языка, которым вы не пользуетесь, и попробуйте вызвать им этот эндпоинт.
Готово, когда: сгенерированный клиент компилируется и доходит до эндпоинта, либо вы можете точно назвать, какой именно пропуск в документе этому помешал.
Частые ошибки
- Описание только успешных ответов — клиенты не могут корректно обрабатывать сбои; исправить: опишите ответы с ошибкой и переиспользуйте общую схему.
- Оставление обязательности неявной — клиент не может понять, будет ли поле присутствовать; исправить: указывайте обязательные поля и допустимость null явно.
- Дублирование схемы вместо ссылки на неё — две копии расходятся; исправить: определите каждую форму один раз и ссылайтесь на неё.
- Хранение спецификации вне репозитория — она устаревает за считанные недели; исправить: версионируйте её вместе с кодом и рецензируйте изменения.
- Отсутствие примеров — отрисованной документацией трудно пользоваться; исправить: приводите реалистичные примеры для каждой операции.
Что читать дальше
- Проектирование API (OpenAPI / Swagger) (05-backend-data/09-api-design-openapi-swagger) — формат, в котором написан этот документ; начинайте с него.
- Контрактное тестирование (05-backend-data/09-api-design-openapi-swagger/02-contract-testing) — как проверить, что реализация всё ещё совпадает с написанным здесь.
- RESTful API (05-backend-data/06-restful-api) — соглашения о ресурсах и кодах состояния, которые описывают схемы.