t0mmy

2020年12月30日に参加

学習履歴詳細

API デザインパターン 24章 バージョン管理と互換性 読了

やったこと

  • API デザインパターン 24章 バージョン管理と互換性 読了

学んだこと

ポイント

  • 互換性の意味
  • 後方互換性の意味
  • バージョン管理の手段
  • バージョン管理のトレードオフ

学び

  • 「互換性」は、二つの異なるコンポーネントが、互いに正常にやり取りできるかどうか
  • 新バージョンのAPIが、旧バージョンAPIを使用したコードでも問題なく動作する場合、後方互換が有るという
    • 後方互換のある変更を、既存のバージョンに加える
    • 後方互換のある変更を、新バージョンとしてリリースする
    • 後方互換の無い変更を、既存のバージョンに加える(基本的に選択しない)
    • 後方互換の無い変更を、新バージョンとしてリリースする
    • コードを変更するときに、後方互換を維持するか議論する必要が生まれる
      • 機能追加、バグ修正など
  • バージョン管理の手段
    • 永続的な安定性
    • アジャイルインスタビリティ
    • セマンティックバージョン管理方式
  • バージョン管理のトレードオフ
    • 細かさと単純さ
    • 安定性と新機能
    • 満足度と偏在度

メモ

WebAPIの更新は難しい。
API利用者に損害を与えることなくWeb APIを変更するにはどうしたらよいか。

「利用者に対応してもらう」は受け入れてもらえない。
「そもそも変更しない」も不可能に近い。

  • セキュリティや法律の問題で改修を余儀なくされる、など

ではどうするか。

概要

チェックポイントやバージョンを導入し、バージョン別にデプロイできる。
利用者に問題を引き起こす可能性のある変更は、別バージョンとしてデプロイする。

バージョン管理の一番の目的は、API利用者に多くの機能を提供しつつ、不便さを最小限に抑えること。

互換性

二つの異なるコンポーネントが、互いに正常にやり取りできるかどうかを示す。
Web API の場合、クライアント、とサーバー間の通信を指す。
APIサーバーに変更を加えても、クライアント側で期待通りの動作をするのであれば、変更前と変更後のバージョンには互換性がある、と言える。

では、互換性(ここでは後方互換性)を持つかどうか、言い換えると、クライアントコードに影響を与えるかは、どう判断するか。

後方互換性を定義する

「後方互換性を有する」を一意に定義することはできない。
言い換えると、API利用者の期待によって変わりえる。
そのため、API提供者側で、APIの「後方互換性」を定義する必要がある。

後方互換性を考える必要がある、一般的な問題を見ていく。

機能追加

機能追加の際、既存のバージョンを拡張するか、新バージョンを発行するか。

新機能を、どう実装するか。

  • 既存のリソースのフィールドを増やす形で実装する
    • メモリがシビアなIoTなどでは、ちょっとしたデータの追加がクラッシュに直結する可能性がある
  • 新しいリソース、またはメソッドとして実装
    • 既存のリソースに影響はない
    • API利用者が、全リソースに対して何らかの処理(バックアップなど)を行っている場合、新規リソースの追加は処理対象の漏れにつながる
  • 既存のリソースに影響を与えるような、リソース、メソッドの新規追加
    • 利用者に新機能の学習を強いることになる

いずれの方法でも、問題は残る。

バグ修正

バグ修正によるリリースも、場合によっては後方互換性を考慮する必要がある。

明確なエラー(500系エラーの修正)は、後方互換性がある。

一方で、400エラーを想定したところ、無意味な値 ({} など)を返していたようなエラーは難しい。

  • API利用者が、 {} が返ってくることを想定したコードを書いている可能性は非常に高い
  • もし 400 エラーを返すようにすると、 {} を期待した既存のコードは動かなくなる
    • つまり、400エラーを返すような修正は、後方互換性が無い

修正方法に正解はなく、「場合による」としか言えない。

強制的な変更の取り扱い

外的要因により、APIの変更を余儀なくされることがある。

  • 例)GDPR導入によるGDPR対応

この時、既存のバージョンを修正するのか、新バージョンとしてデプロイするのか選択する余地がある。
この判断にも正解はなく、「場合による」としか言えない。

  • 新バージョンをデプロイし、徐々に新バージョンへ移行するよう促す
  • 既存のバージョンを修正し、「GDPR施行後、未対応の旧バージョンが使用される」というリスクをシャットアウトする

大事なのは、API利用者の負担を極力減らしつつ、義務付けられた変更を行うこと。

可能な限り事前通知を行い、利用者の作業を最小限に抑え、利用者への影響を少なくすること。

表からは見えない変更

性能の最適化、提供するサービスの精度向上など。

後方互換性があると見なされることが多いが、無いという方向でも成り立つ。

  • 非同期処理を行っていたAPIのレスポンスが、突如 0.1秒未満になると、同期処理が現実味を帯びる
  • 機械学習モデルの変更によるレスポンスの大幅な変化

利用者次第で、後方互換性有とも無しともとられる。

セマンティックスの変化

ここで言う「セマンティックス」は、「動作の変更」や「APIの概念の意味」を指す。

導入する事柄で評価が大幅に変化する。

  • 大きな影響の例 : 新しい権限モデル導入による動作の変化
  • 小さな影響の例 : 配列の順序

既存の利用者と、変更が利用者のコードに与える影響を調べ、利用者に受け入れられるか検討すること。
検討によって、変更を既存のバージョンに組み込むか、独立した新バージョンとしてデプロイするか決定する。

実装

新バージョンの導入方法について学ぶ

  • バージョンの名前は?
  • 旧バージョンは、非推奨となるまで、何日ほど存続させるか?

永続的な安定性

後方互換性のない必要が生じたときに初めて、バージョン管理方式について考えるやり方。
つまり、後方互換性のある変更は、常にバージョンNにマージされる。

バージョン管理の仕組みや方式を全く考慮しない場合に発生しやすい。

無意識に思いつきがちな方式であり、安定する傾向にある。

一方で、細かな変更が重要となるAPI(IoT用など)では受け入れられない。

  • IoTは、ちょっとしたデータの追加でメモリオーバーフローが発生しかねないため、特定のAPIバージョンでフリーズする機能を必要とする

また、後方互換のない変更が増えると、たくさんのバージョンが発生する。

アジャイルインスタビリティ

それぞれのAPIバージョンに、ライフサイクルを示すステータスを付与する方式。

  • Preview => Current => Deprecated => Deleted

Preview ステータスの API バージョンは、開発者が自由に変更できる。
API利用者は、明日にも振る舞いが変わること理解する必要がある。

完成されたものになると、Current ステータスへ移行する。
必須となるパッチ当てやバグ修正だけを行い、互換性のない変更は実装しない。
互換性のない変更は、次のバージョンに追加していく。

古いバージョンのAPIを削除したい場合は、まず Deprecated へ移行し、削除時期を周知する。
時期が来たらAPIを削除し、ステータスを Deleted へ移行する。

Currentステータスのバージョンと、 Previewステータスのバージョンは、常に一つだけ。
これにより、有効なバージョンの数を最小限に抑えつつ、継続的な改良を進めるための強制力として機能させることが出来る。

どのバージョンも、将来的には Deprecated から Deleted へ移行する点が欠点。
つまり、現行バージョンがずっと機能し続ける保証は全くない。

新機能が待ち望まれ、安定している期間が短くても問題ないケースで有効。
反対に、長期的な安定性が求められ、新機能もあまり重要ではないようなケースでは使いにくく感じる。

セマンティックバージョン管理方式

X.Y.Z

  • X : メジャーバージョン。後方互換性のない変更を加える時にインクリメントされる
  • Y : マイナーバージョン。後方互換性のある変更を加える時にインクリメントされる
  • Z : パッチバージョン。後方互換性のある、主にバグ修正などに伴う変更を加える時にインクリメントされる

バージョンが膨大に増え、利用者を混乱させる可能性がある点が欠点。
利用者はできるだけ長い間、特定の非常に細かいバージョンを使い続けたがる傾向にある。

また、全バージョンが永遠にサポートされるわけではない。
非推奨ポリシーを設け、アジャイルインスタビリティのように Deprecated => Deleted となることもある。

利用者は最新バージョンを追求することも、特定のバージョンを使い続けることもできる。

トレードオフ

細かさと単純さ

きめ細かなバージョンを提供するか、後方互換性を維持した少数のバージョンを提供するか、のトレードオフ。

  • 細かさ : きめ細かなバージョンを提供する
    • 特定の安定バージョンをずっと使い続けたい利用者には刺さる
    • 一方で、新規API利用者には、どのバージョンを使えば良いのか惑わせることになる
  • 単純さ : 後方互換性を維持した少数のバージョンを提供する
    • バージョンが少ないため、最適な選択肢を選びやすい
    • 一方で、特定の安定バージョンを求める利用者には刺さらない

安定性と新機能

APIに変更を加える機会を減らして長期間安定させるか、APIにどんどん機能を追加して、一定の期間だけ安定させるか、のトレードオフ。

満足度と偏在度

利用者は多岐にわたるため、API提供側のポリシーが、全利用者に受け入れられる可能性は非常に低い。

一部の利用者の満足度を最大化する方向で意思決定を行うのか、全利用者の使い勝手を最大化する方向で意思決定を行うのか、のトレードオフ。

利用者を「使えない」「不満足」「大丈夫」「満足」の4つに分類すると、以下の通り。

  • 一部の利用者の満足度を最大化する方向 : 「満足」利用者を最大化する事に重きを置く。代わりに、「使えない」「不満足」が増える
  • 全利用者の使い勝手を最大化する : 「大丈夫」利用者を最大化することに重きを置く。代わりに、「満足」が減る

扱うこと

  • バージョン管理とは
  • 互換性とは
  • 後方互換性をどう定義するか
  • バージョン管理手法に伴うトレードオフ
  • Web API のための一般的なバージョン管理手法の概要

まとめ

  • バージョン管理は、API設計者が時間の経過とともにAPIを変更・進化させながら、できる限り利用者に不利益を与えず、多くの改良を提供するためのツール
  • 互換性とは、あるバージョンでのAPIに対して書かれたコードが、別のバージョンに対しても引き続き機能する事を意味する
  • 新しいバージョンは、前のバージョンに対して書かれたコードが期待通りに動作する場合、「後方互換である」という
    • API設計者が利用者の期待をどのように定義するかは、解釈によって変わる
  • 一見無害に見えること(バグ修正など)が後方互換性のない変更に繋がったりする
    • APIの利用者が利用者の期待をどのように定義するかは、解釈によって変わる
WebAPI

2023年12月10日(日)

2.0時間