RESTful API の後方互換性は HTTP より上位の層の問題が大きい

API変更の性格分類とサーバがとりうる対策」再考

まず、APIがどのように変更されるか分類し、サーバが取りうる対策をまとめてみましょう。
(中略)
上記いずれの場合でも、優秀なRESTクライアントならばサーバの応答を理解し、適切に対処できるはずです。

http://d.hatena.ne.jp/IwamotoTakashi/20090504/p1

RESTful API の後方互換性 - 討論妄言録」に対して、id:IwamotoTakashi さんから、このようなご意見をいただきました。

これで対処できるはず、というのは幻想ではないでしょうか。REST 原理主義的な立場をとったとしても、です。少なくとも、後方互換性を破壊するような変更が発生する場合には。後方互換性を破壊するということは、未知の変更がなされるということです。一般に、未知の状況に事前に何の手がかりもなく対応できるようにすることは、非常に困難です。対処しやすくなる (が、クライアントの改修も必要とすることも多い)、というべきでしょう。

もし、事前に対応方法がサービス提供者によって定められているのであれば。それは API の一部ですから、後方互換性を破壊していません。

場合によっては。事前に対応方法が与えられていなくても、クライアント開発者独自の判断で自動対応できるようなプログラムになっていることもあるかもしれません。しかし、これは API で定める範疇にはない動作ですので、ここで問題にすることではありません。投機的判断が成功を収めたにすぎません。

API変更の性格分類とサーバがとりうる対策」は最低限の条件にすぎない

さて。「API変更の性格分類とサーバがとりうる対策」に述べられていることをひとことでまとめると、HTTP (と関連プロトコル) を適切にハンドリングできれば問題にならない、という主張です。HTTP を適切にハンドリングできることは、HTTP アプリケーション (サーバ、クライアントとも含む) には最低限求められる要件です。これを実現できていないのであれば、部分的な実装でしかないので、そもそも救済する対象とはみなせません。

では、HTTP を適切にハンドリングできれば本当に問題にならないのでしょうか。ここで問題視していることは、「十分に動作していたクライアントが、後方互換性を失う API の変更によって動作しなくなること」です。

この問題については、API のうち、要求・応答を行なうための HTTP の層だけを考えるだけでは不十分です。個々のアプリケーションごとに定められる、より上位のプロトコル層まで含めて考えねばなりません。例えば、HTTP 要求・応答文書 (概ねメッセージボディ) の表現形式やスキーマ。あるいは、HTTP アプリケーション (個々のウェブサービス) に固有のワークフローやデータフロー。こういったものを定めるプロトコルが相当します。

クライアントがこれら未対応の状況に遭遇した時に。「エラーで処理できない」として従来の動作を放棄するのも、HTTP 層のみを考えるなら妥当ですし、変更前の API の範疇を越えているので仕様としてもありえる選択です。しかし、ユーザから見れば、機能しなくなった、壊れた、ともすると、不誠実な変更である、となるものでしょう。ユーザの立場を軽視しないのであれば、正常な動作を維持できる手段を取るべきです。

そのためには。これら上位層の変更もクライアントに悪影響を及ぼさないことが望ましいと言えます。さもなくば、クライアントは送受信するデータを適正に扱えず、そのデータを用いるあらゆる処理が機能しなくなる虞があります。

争点は API の安定性

ここまで問題視してきたことは、「後方互換性が気になるのはプロトコル更新時ぐらい」で触れられていますが、とても些細な問題であるかのように述べられているように感じました。*1

しかし、そうだとしたら。クライアント作成者を、契約であるべき API を、軽視していないでしょうか。「API が REST 的であること」は前提条件とした上で*2、「(RESTful API と呼んでいるものが) API として安定であること」を実現するために考えるべきこと、が争点です。繰り返しになりますが、考えるべき層が違います。これらは、ウェブのアーキテクチャではなくアプリケーション固有の問題領域です。ですから、その具体的内容については REST では何も求めていないはずです (もちろん、それらが満たすべき条件は示しています)。

蛇足

ところで。「サーバの応答を理解し、適切に対処」するとはどういうことでしょうか。あるいは「API」とは何でしょうか。もしかすると、この辺りで想定している範囲が異なっているのかもしれません。

と、混乱が見られてきたところで、以下蛇足ですが。ついでなので、「サーバがとりうる対策」それぞれについて、「優秀なクライアント」であっても発生しうる問題を見ておきましょう。

リソースのURIが変わる

変更が URI だけであれば、リダイレクトで対応できる、これはその通りです。HTTP を適切にハンドリングでできることは、クライアントに求められる要件ですので、既知の動作です。つまり、これは後方互換性を破壊していません。

リソースのメディアタイプが変わる

従来の API の範疇で、コンテントネゴシエーションによって従来の上位互換になっている応答文書を取得できるのであれば。HTTP 仕様に従って適切にハンドリングするだけですね。後方互換性を破壊していません。

そうでない場合。例えば、従来は XML 文書しか返さないことになっていたのに、JSON 文書しか返さなくなるような変更。あるいは、同じメディアタイプの XML 文書であるが、重要な要素名が変わるような変更。こういった場合に、どんなに優秀なクライアントであっても、事前に対応できるようにするのは非常に困難です。多くの場合、クライアントプログラムの改修が必要になるでしょう。

サーバが処理可能なリクエストエンティティのメディアタイプが変わる

受理可能な要求文書のメディアタイプのいずれかが従来の上位互換になっていて。従来の API の範囲で適切にコンテントネゴシエーションを行なえるのであれば。同じく、後方互換性を破壊していません。

そうでない場合、やはり後方互換性を破壊するような未知の変更に、あらかじめ対処しておくことは困難でしょう。

メディアタイプは変わらないが、入力パラメータが変わる

これは多くの場合、後方互換性を破壊するでしょう。修正ヒントが応答されたとして、それをクライアントプログラムが自動的に適切な対処をできるでしょうか。一般には非常に困難でしょう。

修正ヒントの記述方法および解釈方法が事前に決められているのであれば。自動的に対処するようなクライアントを実装することは可能です。但し、事前に更められた修正ヒントの記述・解釈方法は API の一部とみなされるべきものです。つまり、これは後方互換性を破壊しない場合に相当します。

*1:それは問題ではない (RESTful API では後方互換性を気にする必要がない)、解決法は単純である (API変更の性格分類とサーバがとりうる対策)、という流れだと理解していたのですが。同じようにするかもしれない (後方互換性が気になるのはプロトコル更新時ぐらい)、というまとめかたなので。異議だったのか、別の解決法の提示だったのか、同意だったのか、(便乗気味に) REST のことを語るものだったのか、ちょっと分からなくなりました。ので、この辺りの記述は混乱気味になっているかもしれません ^^;

*2:と言う辺り、かなり原理主義的立場に近いと言えるかもしれません