Прямой ответ
API versioning — практика управления версиями API для обеспечения обратной совместимости (versioning — «версии API» — versioning — incident — «эволюция API» — versioning), зачем: обратная совместимость (versioning — «старые клиенты работают» — versioning — incident — «не ломать клиентов» — versioning — api — «совместимость» — versioning); стратегии версионирования (versioning — «как версионировать» — versioning): (1) URI Versioning (versioning — «версия в URI» — versioning — incident — /api/v1/users (versioning — «версия в пути» — versioning — api — «URI» — versioning — «явно видно» — versioning); (2) Header Versioning (versioning — «версия в заголовке» — versioning — incident — Accept: application/vnd.api.v1+json (versioning — «версия в заголовке» — versioning — api — «заголовок» — versioning — «чище URI» — versioning); (3) Parameter Versioning (versioning — «версия в параметре» — versioning — incident — /api/users?version=1 (versioning — «версия в параметре» — versioning — api — «параметр» — versioning — «гибко» — versioning); (4) Semantic Versioning (versioning — «мажор/минор/патч» — versioning — incident — 1.0.0 (versioning — «семантическое версионирование» — versioning — api — «semver» — versioning — «мажор — breaking changes» — versioning); обратная совместимость (versioning — «старые клиенты работают» — versioning): (1) Добавление полей (versioning — «новые поля не ломают» — versioning — incident — «добавление безопасно» — versioning — api — «добавление» — versioning — «обратная совместимость» — versioning); (2) Удаление полей (versioning — «удаление ломает» — versioning — incident — «удаление опасно» — versioning — api — «удаление» — versioning — «breaking change» — versioning); (3) Изменение полей (versioning — «изменение типа/формата ломает» — versioning — incident — «изменение опасно» — versioning — api — «изменение» — versioning — «breaking change» — versioning); деприкейшн (versioning — «устаревание» — versioning): (1) Объявление (versioning — «объявить устаревание» — versioning — incident — «предупредить клиентов» — versioning — api — «деприкейшн» — versioning — «заранее» — versioning); (2) Поддержка (versioning — «поддерживать старую версию» — versioning — incident — «дать время мигрировать» — versioning — api — «поддержка» — versioning — «месяцы/годы» — versioning); (3) Удаление (versioning — «удалить старую версию» — versioning — incident — «после миграции» — versioning — api — «удаление» — versioning — «когда все мигрировали» — versioning); когда версионировать (versioning): публичные API (versioning — «внешние клиенты» — versioning — incident — «не ломать клиентов» — versioning — api), breaking changes (versioning — «ломающие изменения» — versioning — incident — «новая версия» — versioning — api), эволюция API (versioning — «API меняется» — versioning — incident — «версии» — versioning — api); антипаттерны: ломать без версионирования (versioning — «изменения без версии» — versioning — incident — «клиенты ломаются» — versioning — api — «версионирование обязательно» — versioning), вечная поддержка всех версий (versioning — «поддерживать все версии» — versioning — incident — «накладные расходы» — versioning — api — «деприкейшн нужен» — versioning).
Практика: версионирование REST API
URI Versioning (versioning — @GetMapping("/api/v1/users") public List<User> getUsersV1() { ... } @GetMapping("/api/v2/users") public List<UserV2> getUsersV2() { ... } (versioning — «версия в URI» — versioning — api — «URI» — versioning — incident); Header Versioning (versioning — @GetMapping(value = "/api/users", headers = "X-API-Version=1") public List<User> getUsersV1() { ... } @GetMapping(value = "/api/users", headers = "X-API-Version=2") public List<UserV2> getUsersV2() { ... } (versioning — «версия в заголовке» — versioning — api — «заголовок» — versioning — incident); OpenAPI (versioning — openapi: 3.1.0 info: title: My API version: 1.0.0 (versioning — «OpenAPI спецификация» — versioning — api — «OpenAPI» — versioning — OpenAPI — «документация» — versioning); Деприкейшн (versioning — @Deprecated @GetMapping("/api/v1/users") public List<User> getUsersV1() { ... } (versioning — «устаревший эндпоинт» — versioning — api — «деприкейшн» — versioning — incident).
Практический сценарий: эволюция API с версионированием
Контекст: API (api — публичный (incident — versioning), боль: нужны изменения (versioning — «изменения в API» — versioning — incident — «не ломать клиентов» — versioning — api); решение — API versioning: (1) URI versioning (versioning — @GetMapping("/api/v1/users") (versioning — api — «версия в URI» — versioning — incident); (2) новая версия (versioning — @GetMapping("/api/v2/users") (versioning — api — «v2» — versioning — incident); (3) обратная совместимость (versioning — v1 работает (versioning — «старые клиенты» — versioning — api — «совместимость» — versioning — incident); (4) деприкейшн (versioning — @Deprecated (versioning — «v1 устаревает» — versioning — api — «деприкейшн» — versioning — incident); (5) миграция (versioning — клиенты мигрируют (versioning — «на v2» — versioning — api — «миграция» — versioning — incident); (6) удаление (versioning — v1 удаляется (versioning — «после миграции» — versioning — api — «удаление» — versioning — incident); результат: API эволюционирует (versioning — «v1 → v2» — versioning — incident — «клиенты не ломаются» — versioning — api — «обратная совместимость» — versioning — «миграция» — versioning); вывод: API versioning решили задачу (эволюция без breaking changes — versioning — ADR — «ломать без версионирования» — антипаттерн — api — версионирование обязательно — versioning — техдолг).
FAQ
Что такое API versioning и какие стратегии существуют?
API versioning (versioning — практика управления версиями API (versioning — «версии API» — versioning — incident — «эволюция API» — versioning — api); стратегии (versioning): URI (versioning — «версия в URI» — versioning — incident — /api/v1/users (versioning — api — «URI» — versioning), Header (versioning — «версия в заголовке» — versioning — incident — Accept: application/vnd.api.v1+json (versioning — api — «заголовок» — versioning), Parameter (versioning — «версия в параметре» — versioning — incident — /api/users?version=1 (versioning — api — «параметр» — versioning), Semantic (versioning — «мажор/минор/патч» — versioning — incident — 1.0.0 (versioning — api — «semver» — versioning); «API без версионирования» — антипаттерн (клиенты ломаются — api — версионирование обязательно — versioning — ADR — техдолг).
Что такое обратная совместимость и как её обеспечить? Обратная совместимость (versioning — «старые клиенты работают» — versioning — incident — «не ломать клиентов» — versioning — api — «совместимость» — versioning); как: добавление полей (versioning — «новые поля не ломают» — versioning — incident — «добавление безопасно» — versioning — api — «добавление» — versioning), не удалять (versioning — «удаление ломает» — versioning — incident — «удаление опасно» — versioning — api — «удаление» — versioning), не изменять (versioning — «изменение типа ломает» — versioning — incident — «изменение опасно» — versioning — api — «изменение» — versioning); «ломать обратную совместимость» — антипаттерн (клиенты ломаются — api — обратная совместимость обязательна — versioning — ADR — техдолг).
Как правильно деприкейтить старую версию API?
Деприкейшн (versioning — устаревание (versioning — «объявить устаревание» — versioning — incident — «предупредить» — versioning — api — «деприкейшн» — versioning); как: объявление (versioning — @Deprecated (versioning — «устаревший» — versioning — api — «деприкейшн» — versioning — incident), поддержка (versioning — «поддерживать» — versioning — incident — «дать время» — versioning — api — «месяцы/годы» — versioning), удаление (versioning — «удалить» — versioning — incident — «после миграции» — versioning — api — «когда все мигрировали» — versioning); «удалить без деприкейшна» — антипаттерн (клиенты ломаются — api — деприкейшн обязателен — versioning — ADR — техдолг).
Когда нужно версионировать API и когда можно обойтись без версий? Нужно (versioning — публичные API (versioning — «внешние клиенты» — versioning — incident — «не ломать клиентов» — versioning — api), breaking changes (versioning — «ломающие изменения» — versioning — incident — «новая версия» — versioning — api), эволюция (versioning — «API меняется» — versioning — incident — «версии» — versioning — api); Можно без (versioning — внутренние API (versioning — «внутренние клиенты» — versioning — incident — «можно координировать» — versioning — api), стабильные API (versioning — «не меняется» — versioning — incident — «версии не нужны» — versioning — api); «версионирование для всего» — антипаттерн (внутренние API — можно без — api — выбор по задаче — versioning — ADR — техдолг).
Источники: OpenAPI, Swagger specification, Martin Fowler (versioning APIs) — ссылки в шапке.