web-dev-qa-db-ja.com

REST API列挙型フィールドを下位互換性を維持しながら拡張する方法

エンドポイントがあると想像してくださいGET /v1/statusこれは、文書化されている事前定義状況の1つを返します。たとえば、[disabledenabled]のいずれかです。エンドポイントは、他のサードパーティのサービスで使用できます。

blockedステータスをそのまま追加するだけで発生する問題は、サードパーティのクライアントがこのケースを処理できないか、次のようなものになる可能性があることです。

if (status == 'disabled') {
  // do something when status disabled
} else {
  // do something when status enabled
}

バージョンをバンプして2つのバージョンを維持することは、このような小さな変更に対する適切な解決策のようには見えません。

このエンドポイントに依存している可能性のあるサードパーティのクライアントを壊すことなく、blockedなどの新しいステータスを追加するための最良のアプローチは何ですか?または、今後このような問題を回避するためにパブリックAPIを設計または文書化するためのより良い方法は何ですか?

5

エンドポイントが返す列挙を拡張してエンドポイントが返すものを変更することは、下位互換性のある変更ではありません。 (一方、エンドポイントに提供される列挙を拡張すると、)

これは、現在の問題に対する2つの可能な解決策を示しています(バージョン番号を増やす以外に)。1)列挙を拡張せずに、他の方法で追加情報を渡すか、2)新しいエンドポイントを使用します。これらのアプローチはどちらも、古い方法でインターフェースを使用するために新しい情報が必要ないとは想定していません。しかし、もちろん、これは下位互換性と同じです。最初のアプローチは、statusエンドポイントから本文、ヘッダー、または可能性としてはHTTPステータスコードを介して「理由」を返す形式を取る可能性があります。後者は、前のアプローチで説明した「理由」を返す可能性のある新しいエンドポイント、statusDetailsなどです。実際、この2番目のアプローチは最初のアプローチにすぎませんが、新しいエンドポイントを使用して情報を提供します。私は推測していますが、APIを使用するプログラムに対して「ブロック」と「無効」の間に大きな違いはないのではないかと思います。この2つの違いは、の問題です。 why有効になっていません。つまり、消費者が「ブロック」を「無効」として扱ったとしても、正しく機能します。

私の推測が正しい場合、元のデザインは完全に合理的であるように見え、それは合理的ではない(下位互換性がある以外に)新しいアプローチです。新しいアプローチは ブール値をTrueFalseFileNotFound に変更するように聞こえます。私の推測が正しくない場合、エンドポイントの意図を知らなければ、何が妥当であるかを言うのは困難です。たとえば、単に「情報提供」を意図したものである場合、文字列などのオープンデータ型は、誤用を防ぐためにドキュメントで提供されている非常に弱い保証で使用されているはずです。または、それが状態マシンの状態に近い場合、少なくとも、異なる名前が使用されているはずであり、状態マシンに新しい状態を追加することは、後方互換性のない変更であり、まったく「小さな」ものではありません。 。これは、REST APIの場合は非常に珍しい設計選択です。

クライアント側でそれを回避する方法は、ifステートメントに組み合わせを明示的にリストし、DykstraのGuarded Command Language GCLのスタイルがあまりない場合は失敗することです。

それは私の習慣であり、必ずしも他の人がすることではありません。

そうは言っても、バージョンバンプが必要な場合や、現在のバージョンのコントラクトへの補足が提供されている場合など、すべての状況で下位互換性がないAPI変更を行っていると言えます。

1