BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース RESTfulサービスにおいて部分的更新を実装する

RESTfulサービスにおいて部分的更新を実装する

原文(投稿日:2010/11/19)へのリンク

最近Alex Scordellis氏は、リソースの部分的更新についてのクライアントとRESTfulサービスのインタラクションがどのようにモデル化され、デザインされ得るかについての記事を投稿した

Ian Robinson氏、Jim Webber氏、Savas Parastatidis氏による書籍REST In Practiceの中に]私は不可解な考えを1つ見つけました。著者たちはリソースの状態を更新するものとしてPOSTを推奨しています。これは、PUTのセマンティクスの解釈の選択によって導かれるものです。HTTP仕様によれば
Request-URI が既に存在するリソースを参照している場合は、同封されるエンティティはオリジンサーバにあるそれの修正版とみなされるべきである。

本の中では、著者たちはこのことを、PUTリクエストに同封されるボディはそれと同じURIへのGETリクエストによって得られる同じ要素の表現を含むべきだ、という意味に解釈しています。私たちはHATEOAS形式を使っているので、表現には、リンクやほかのハイパーメディア・コントロールが含まれます。したがって、クライアントはビジネスデータ(例えば、コーヒーの注文の新しい内容)とハイパーメディア・コントロール(ワークフローにおける次の利用可能なステップ)の両方を含んだ表現をPUTすべき、ということのようです。

Alex氏は、サービスから得られるハイパーメディアとリソース表現によってクライアントのワークフローは駆動されるべき、という意見であり、この相互作用をモデル化し得る4つの方法を提案している。これらの例のうちいくつかは、RESTBucksに関する記事を参照している。

PATCHを使う
[…]広くサポートされていない方法で、私は意味的には間違いだと感じています。クライアントの視点からみれば、オーダーを構成するビジネスデータ(ラテが何杯か?)がリソースのすべてです。クライアントはこれをPATCHとはみなさず、置換すなわちPUTとみなすでしょう。PATCHは"私がもともと注文した脂肪分の多いミルクの代わりに、脱脂乳をラテに使う"というような概念を表現するのには意味があるかもしれません。
POSTを使う
これは本の中で提案されている方法です。私は、この方法はPATCHと同様の欠点を持っていると考えます。POSTはリソースへ追加するという意味合いを持っています。コーヒーの注文リソースに1杯のカプチーノをPOSTすることは、そのもとあったコーヒーの注文を1杯のカプチーノで置き換えるのではなく、カプチーノを追加すべき、というように感じます。
ハイパーメディアを含むPUTを使う
PUTは完全な表現を含むべきという厳密な解釈に従えば、クライアントは新しいコーヒーの注文全体と、サービスがその注文を最後に送ったハイパーメディア・コントロールのすべてを送ることになります。
ハイパーメディアを含まないPUTを使う
クライアントは新しい注文の完全な表現を送りますが、リンクは送りません。私は、これが概念的には正しいように思います。クライアントは、その責任範囲であるデータの一部については完全な表現を送ることでPUTに対する期待を満足させる一方、どんなハイパーメディア・コントロールが利用可能かを決定することに責任を負うかのようなふりをすることがないからです。

@serialseb@iansrobinson@jimwebberとの議論のあとで、Alex氏は動詞PUTの意味的期待も満たす経験則を導いた。

GETリクエストに対するレスポンスとして、サービスはビジネスデータ、利用可能なハイパーメディア・コントロールの両方を含む現在既知の状態の完全な表現を提供する。クライアントは、その責任範囲にある部分の完全な表現をPUTする。

William Vambenepe氏はこの議論に新たに考察を加えている

シンプルな例をとりあげてみます。部分的更新において要素がない場合、何を意味するのでしょうか? 明示的な省略、つまりその表現でこの要素の削除の必要性を表現しようとしている、ということでしょうか? それとも“現在の値を変更しない”という意味でしょうか? 仮に後者だとしたら、どのように削除を表現するのでしょう? 部分的なPUTがあるように部分的なDELETEも必要なのでしょうか? ありがたいことにその必要はありませんが、PUTの一部として要素の削除を行うメカニズムをもつ必要があります。Empty値? いや、それは必ずしも要素がないということと同じことを意味するわけではないでしょう。Nil値? これをJSONでどう扱うのでしょう?

彼はリソースの部分的更新のインタラクションのデザインの問題は難問であり、WSDM、WS-Management、WS-ResourceTransferといった仕様の中ですでに解決が試みられてきた、と強く主張している。

よいニュースは、これまでにたくさんの間違いをおかしてきたし、いくつかの教訓を学んできてもいる、ということです(この技術的な大言壮語やこのふり返り、または実験をみてください)。悪いニュースはまだ多くの新しい間違いがおかされるのを待っている、ということです。

Stu Charlton氏もまた、この問題の議論に割って入り、RESTfulハイパーメディアは実のところデータモデルを記述することができないという事実を批判的に主張した。彼によれば、RESTfulサービスがよりよい相互運用性を発揮するために必要な以下の2つのことがある。

(a)一般的ユースケースの80%をカバーし、JSONやXMLフォーマットを持つ[閉じた]データモデル

(b)リソースのライフサイクルや状態遷移を記述するユースケースの80%をカバーするメディアタイプ -- 言い換えると、ハイパーメディアにおいてPOSTを自己記述的にすること。コンピューティングの世界はデータを更新することだけについてのものではなく、抽象概念についてのものだからです。

Alex氏の投稿へのコメントで、Duncan Cragg氏は現実的な解決策を持ち込んだ。

2つのリソースを持つべきです:サーバにクライアントが何を望んでいるかを表すクライアントの注文と、クライアントに戻す詳細を確かめるサーバ"チケット"です - そして必要なら追加データ、リンクなどをすべて加えます。サーバチケットはクライアントの注文に対する依存関係があり、さらに、内部あるいは外部のプロセス状態に関しては、その注文の実行中は内部を把握しています。しかし、誰がクライアントの注文をホストするのでしょうか? もちろん、クライアントに決まっています! いや、非対称な構成をとっていなければ、です。その場合にはクライアントは注文をサーバのどこかにPOSTかつ/またはPUTすることができます。こうすれば、クライアントはサーバ側が生成したどんなビットも気にすることなく、オーダーリソース全体を一度に登録し、変更することになります。

この問題を解決するためにたくさんの提案が行われてきた。そして、リソースを適切にモデル化すれば、問題は容易に解決するようだ。多くの場合、ただリソースをCRUDをサポートするエンティティとして考えることによってそれは問題となり、Duncan Craggs氏の例で示したようにリソースを“リソース”とサービスとしてモデル化することによって解決に導かれる。オリジナル記事そのコメントを必ずチェックし、このフォーラムであなたの意見を展開して欲しい。

この記事に星をつける

おすすめ度
スタイル

BT