Hatena::ブログ(Diary)

winplusの日記 このページをアンテナに追加 RSSフィード

2012-07-11

ハイパーリンクはリソースを繋ぐ

以下のブログを読んで思ったことをメモしておきます。議論のポイントを把握できていないかもしれませんが、自身の理解のために。

ハイパーリンクは何を繋ぐのか - 檜山正幸のキマイラ飼育記 (はてなBlog)

ハイパーリンク設計をサーバーサイド設計に従属させるべきではない - 檜山正幸のキマイラ飼育記 (はてなBlog)


まず、ある検索サービスがあって、RESTという単語で検索したとします。

http://www.example.com/search?q=REST

最初の10件の検索結果が返ってきました。この検索結果には、続きを表示するためのリンクがあります。

http://www.example.com/search?q=REST&move=next

返ってきたページにも、さらにその続きを表示するためのリンクがあります。

http://www.example.com/search?q=REST&move=next

最初のページにあるリンクと次のページにあるリンク(のURL)は同じです。このリンクが機能するためには、現在クライアントが表示しているページがどこであるかという情報が必要です。これがアプリケーション状態。アプリケーション状態をサーバーが保持していないと、このリンクは機能しません。

ところで、最初の10件を表示したページの続きを表示するためのリンクが次のようなものであったらどうでしょう。

http://www.example.com/search?q=REST&start=10

返ってきたページにある、さらにその続きを表示するためのリンクもこうなります。

http://www.example.com/search?q=REST&start=20

この場合は、現在表示しているページがどこであるかという情報は不要です。なので、サーバーはアプリケーション状態を保持しません、これがステートレス。ステートレスなリンクは、クライアントの状態にかかわらず、URLで指定されたサーバー上のリソースを返します。ということで、リンクはリソースを繋ぐものだということになります。


では、ブログの例を見てみましょう。

僕(hiyama)が、http://hiyama.example.com/blog/というURLのブログを持っているとしましょう。次の操作をしたとします。

  1. http://hiyama.example.com/blog/の画面から、http://hiyama.example.com/blog/entry123 へのアンカーをクリック。
  2. http://hiyama.example.com/blog/entry123 の画面を眺めてから、編集ボタンをクリック。
  3. 編集画面で編集を行なってから、保存ボタンをクリック。
  4. 編集後の http://hiyama.example.com/blog/entry123 の画面を再び眺める。「うん、これでよし。」

4つのアプリケーション状態と3回の状態遷移のあいだ、相手にしているサーバー側リソースはhttp://hiyama.example.com/blog/entry123 だけです(黒丸がそれ)。アプリケーション状態の遷移をリソース間のリンクとは考えにくいです。

ひっかかるのは「状態3」のところです。たとえば、「状態2」がブログの記事を表示している状態であり、「状態3」が編集可能なようにフォームを含むHTML画面だとすれば、これらは別のURLを持つことになると思うのです。

http://hiyama.example.com/blog/entry123/edit

あるいは

http://hiyama.example.com/blog/entry123?edit=true

で、これが別のリソースかどうか、というのが分かれ目になる気がします。

これが別リソースだとみなせば、リンクはリソースを繋ぐものという先の理解で問題ないでしょう。あらゆるアプリケーション状態(※)をリソースとしてマッピングし、アプリケーション状態の遷移をリンクで実現しようとするのがROAだ、といってもいいのかもしれません。

いや、リソースはあくまでhttp://hiyama.example.com/blog/entry123だ、ということであれば、アプリケーション状態とリソースとが対応しないこともあるでしょう。最初にあげた検索結果の例でもそうです。「リソース=検索結果全体」であり、その一部をクエリー文字列で制限して表示しているとみなせば、次ページへの遷移はアプリケーション状態の遷移であって、リソース間の遷移ではありません。「リソース=RESTという単語で検索したその10番目から10個の結果」だとすれば、次ページへの遷移は「RESTという単語で検索したその20番目から10個の結果」という別のリソースへの遷移だといえます。


僕の感覚では(感覚ですけどね)、URLは単なるキー文字列や引数データではなくて、サーバー側に永続的に存在している“実体”に対応して欲しいのです。

URLに関する議論 -- なぜ僕はクエリパラメータを擁護、ときに推奨するのか - 檜山正幸のキマイラ飼育記 (はてなBlog)

この“実体”がリソースであり、さらに、それはURLのパス部分で一意に指示できるべきである、ということになるのでしょう。「感覚」としては分かりますし、確かにきれいだと思います。そして、この「感覚」は、ROAとは相容れません。

通常、リソースとは、コンピュータ上に格納することができ、一連のビットで表せるものである。たとえば、ドキュメント、データベースの行、またはアルゴリズムを実行した結果などである。

p85.『RESTful Webサービス

“実体”のない、たとえば「アルゴリズムを実行した結果」であってもリソースである(として扱う)のがROAの立場です。だからROAでは、ハイパーリンクはリソースを繋ぐのです。


※クライアント側だけで完結するアプリケーション状態は考慮していません。参照iwamotのブログ : 「アプリケーション状態」を正しく理解したい


追記

ハイパーメディア・アプリケーションにおける「サバー vs. クライアント」の問題 - 檜山正幸のキマイラ飼育記 (はてなBlog)を読みました。抽象的な議論についていけていないので(すみません、いなくなる方です)、また具体例に引き戻して、なんとか理解しようとしています。

問題1
あるクライアントがブログの記事を表示している。これを編集できる状態にしたい。どのようなリクエスト・レスポンスが最適なのか?
問題2
あるブログの記事がある。これを編集するための画面がある。この2つを繋ぐには、どのようなリクエスト・レスポンスが最適なのか?

問題1を考えるときに問題2の形に制限する必要はない、ということかなあ。たしかに出発点は問題1なんだけれど、とりあえず問題2に変更した上で(あるいはなんとか問題2のように変形して)、考えていますね。

tkawatkawa 2012/07/15 19:11 とてもわかりやすいです。檜山さんの例については、僕の理解もちょっとずれているかもしれませんが。
檜山さんの立場では、「HTTPメソッドと標準化された動詞の組み合わせ」をURL(リソース)に作用させるというもので、その中に動詞editも存在します。これはRESTの統一インターフェイス制約という意味では適合していますが、ROAはHTTP標準メソッドに拠っているので、すでにかなり乖離があります(RESTful Webサービス p.109)。
もしくは、ここでいう「リソース」とは、厳密には「リソースの表現(representation)」というべきなのかもしれません。「編集可能なようにフォームを含むHTML画面」は、同一リソースの別表現とも解釈できます。
ただし、結局ROAと相容れないというのは同感です。
「RESTful Webサービス」は、4章以降は全部ROAを前提とした説明なので、違和感があるのはある意味当然ではないかと思います。

winpluswinplus 2012/07/16 11:54 コメントありがとうございます。
いろいろ考えていたら長くなりそうだったので、別記事にしました。ご参照いただけると幸いです。

トラックバック - http://d.hatena.ne.jp/winplus/20120711/1341999219