檜山正幸のキマイラ飼育記 このページをアンテナに追加 RSSフィード Twitter

キマイラ・サイトは http://www.chimaira.org/です。
トラックバック/コメントは日付を気にせずにどうぞ。
連絡は hiyama{at}chimaira{dot}org へ。
蒸し返し歓迎!
このブログの更新は、Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama
ところで、アーカイブってけっこう便利ですよ。

2012-07-05 (木)

ハイパーリンクは何を繋ぐのか

| 13:09 | ハイパーリンクは何を繋ぐのかを含むブックマーク

[追記]

この記事内で、既存の用語の意味をズラシたり拡大解釈して記述したところがあります。「既存の解釈に強く拘らない」というのがひとつの(僕が推奨する)方策ですが、「もう少し、ハイパーメディア・アプリケーションについて」も一緒に読んでくださるのがヨイかと。

[/追記]

『RESTful Webサービス』という本はよく参照しましたし、このブログ内でも何度か言及・引用しています。

RESTful Webサービス

RESTful Webサービス

この本はたいへん勉強になりました。しかし、多少の違和感が残る、なんか不足を感じる点もあります。この本の著者達、リチャードソン&ルビーと僕のあいだで、どこかに認識やメンタルモデルの食い違いがあるみたいです。それは(仮にあったとしても)微妙な点なので、なかなか明文化はしにくいものです。

最近また『RESTful Webサービス』をパラパラと見ていて、「アレッ?」と思ったフレーズがあったので、その周辺を紹介してみます。幾分かは、僕の違和感/不足感の説明になるでしょう。

内容:

  1. アプリケーション状態
  2. 接続性
  3. 具体例
  4. ハイパーリンクは何を繋ぐのか

アプリケーション状態

まず、アプリケーション状態という言葉ですが、95ページに「クライアント側で維持される状態」と定義されています。具体例による説明は次のようなものです。

検索エンジンを使用する際、現在のクエリと現在のページはアプリケーション状態である。この状態はクライアントごとに異なる。あるユーザーが「クラゲ」の検索結果の3ページ目を表示していて、別のユーザーが「ネズミ」の検索結果の1ページ目を表示しているとしよう。ページ番号とクエリが異なるのは、両者がアプリケーションで異なるパスをたどったためだ。それらのクライアントに格納されるアプリケーション状態はそれぞれ異なる。

「現在のページ」もアプリケーション状態の一部のようなので、「アプリケーション状態=画面+クッキーデータなど」と考えればよさそうです*1。僕はそのような理解をしてます。もちろん、「画面」という概念がないなら解釈に修正が必要ですが、クライアントが「利用者に同じ情報を提供し、利用者の操作に同じように反応するなら、同じアプリケーション状態にある」と言っていいでしょう。

接続性

『RESTful Webサービス』の100ページで「アプリケーション状態エンジンとしてのハイパーメディア」(Hypermedia As The Engine Of Application State)に少し触れた後で、この言葉より「接続性(Connectedness)」という言葉を使うよ、てなことが書いてあります。

リンクを持つという特性を、接続性(Connectedness)と呼ぶことにする。Webサービスは、ユーザーがリンクをたどり、フォームに記入するだけで、サービスを別な状態へ移行できる範囲まで接続される。これを「接続性」と呼ぶのは、「アプリケーション状態エンジンとしてのハイパーメディア」と呼んだのでは、概念が実態以上に難しくなってしまうからだ。筆者が言いたいのは、リソースをそれらの表現において相互にリンクすべきだということである。

最後のほうにある「リソースを相互にリンクする」ということが、僕には不自然に思えます。なぜなら、ハイパーリンクによりリンクされる対象はリソースではなくてアプリケーション状態だと思っているからです。

もともとの「アプリケーション状態エンジンとしてのハイパーメディア」の「状態エンジン」とは、「アプリケーション状態の遷移を引き起こす駆動装置」という意味ではないのでしょうか*2。「クライアント側のアプリケーション状態」を「サーバー側のリソース状態」にいつの間にかすり替えているように思えます。

具体例

具体例で話しましょう。

僕(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メソッドと動詞(「そろそろ決着、HTTPメソッド、URL、そして標準化された動詞」を参照)です。

  1. 「HTTPメソッドGET + 動詞view」で状態1から状態2に遷移
  2. 「HTTPメソッドGET + 動詞edit」で状態2から状態3に遷移
  3. 「HTTPメソッドPOST + 動詞save」で状態3から状態4に遷移

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

ハイパーリンクは何を繋ぐのか

アプリケーション状態とリソースをノードとして、リクエストの辺とレスポンスの辺で繋ぐと、有向二部グラフができます。中間のノードを省略して描き直せば、アプリケーション状態の遷移グラフとリソースのリンクグラフとなります。これらは、ある種の双対とも言えるので、どちらか一方の情報から他方の情報を推測することはできます。

だから、“ある程度”は相互に変換できるとも言えますが、「ハイパーリンクはリソースのリンクだ」と言ってしまうと精密さを失います。『RESTful Webサービス』で採用している立場は「リソース指向」と銘打っているので、「サーバー側の状態=リソース状態」を中心に考える、ということなのでしょう。ですが、僕は「クライアント側の状態=アプリケーション状態」を中心に考えるべきだと思っているので、そこらへんで食い違いが出てるのかもしれません。

*1:実際に目に見えているビジュアルとしての画面というより、画面を識別するデータという感じでしょうが。

*2:原典にはまったく当たってないので、単なる憶測です。

IwamotoTakashiIwamotoTakashi 2012/07/05 21:06 著者の意図を汲むと、95ページの例では「現在のページ」は「現在のページ番号」を指しているのだと思います。あるユーザーが「何を検索していて何ページ目にいるのか」がアプリケーション状態である、と。

m-hiyamam-hiyama 2012/07/06 08:25
IwamotoTakashiさん
> ユーザーが「何を検索していて何ページ目にいるのか」がアプリケーション状態である、と
そうですね、そう解釈するのがあってると思います。
注釈*1に、「実際に目に見えているビジュアルとしての画面というより、画面を識別するデータという感じでしょうが。」と書いたように、
僕も、人が目で見ているホンモノの画面イメージを「状態」と考えたいわけではありません。
でも、アプリケーション状態の説明やらメンタルモデルとしては、「画面」が一番わかりやすいと想います。

IwamotoTakashiIwamotoTakashi 2012/07/06 12:14 すみません、注釈を見落としていました。
僕はアプリケーション状態を、93ページに書かれているFTPの作業ディレクトリとのアナロジーで理解しています。ステートフルなプロトコルであればサーバー側が維持するはずのクライアントの状態、それをRESTful Webでは「アプリケーション状態」とよぼう、というような。「画面」もそうなのかもしれませんが、僕にとってはちょっと分かりづらい感じです。
たぶん僕の頭が悪いせいなので、6日の記事も合わせて、もう少し考えてみます。

m-hiyamam-hiyama 2012/07/06 12:24 IwamotoTakashiさん、
> 注釈を見落としていました。
まっ、注釈ですからね。
> 僕にとってはちょっと分かりづらい感じです。
一連の記事とコメントのなかで、「感覚」「感情」「メンタルモデル」なんて言葉を頻繁に使ってますよね。
http://d.hatena.ne.jp/m-hiyama/20120702#c1341219546 では、
> この種の議論では、万人を納得させるような説得的な根拠は示せないんじゃないかと思っています。
と言っています。

同じ現象を同じ場所から見ても、違う人の心に映る内的景色は違うんじゃないかと思うんですよ。
ですから、「分かりやすい」とか「自然に思える」とかも、バイアスがあるのが前提です。
この前提は常に存在するので、自明としていちいち注意はしてませんけど。

RikaTRikaT 2012/07/08 02:56 http://www.chimaira.org/img3/app-state-trans-3.gif
ですが、1.-4.で言葉で書かれている説明とちょっと違うような気がするのですが、これで正しいのでしょうか? 1.で/blogにGETを送ると書いているように見えますが、図では/blog/enrty123にアクセスしているように見えます。URLがリソースを示すRESTfulなモデルでは、URLは重要な違いかと思います。

RikaTRikaT 2012/07/08 03:07 失礼、別記事へのリンクで理解しました。

>ハイパーリンクによりリンクされる対象はリソースではなくてアプリケーション状態
というのは、元の語彙からするとちょっと奇妙な感じがします。
リンクはURLを示すもので、URLはサーバーサイドへのアクセス先を示すものなので、アプリケーション状態(クライアントサイド)に対してはどうやってもリンクできないかと思います。
この本で言うハイパーリンクとは、30x系レスポンスに含まれるLocationヘッダーなどが最たる例かと思います(もちろんエンティティボディ内のURLもそうだと思いますが)。

アプリケーション状態が非ログイン状態のクライアントがアクセスしたら、あなたはログインしてから来てね、ということでログインできるURLを返し、ログインされた状態のユーザーであればコンテンツを返す、とか。

アプリケーション状態を変化させるのは、リソースへのアクセス結果(サーバー側のレスポンス)ですよね?

m-hiyamam-hiyama 2012/07/09 08:39
RikaTさん、
ご指摘の件は、僕の主張を再確認するよい題材です。

> 1.で/blogにGETを送ると書いているように見えますが、
1. の文面をそのまま引用すると:
>> http://hiyama.example.com/blog/ の画面から、
>> http://hiyama.example.com/blog/entry123 へのアンカーをクリック。
「GETを送る」行為は「http://hiyama.example.com/blog/entry123 へのアンカーをクリック」ですよね。
このときのURLは、/blog ではなくて、/blog/entry123 です。

> 図では/blog/enrty123にアクセスしているように見えます。
1と番号が振られた状態において、ユーザー(ブラウザを見ている人間とします)は、http://hiyama.example.com/blog/ のページを見ています。
このページには、例えば最近のエントリー10個へのリンクがあると想像してください。
ここで、とあるリンクを選んだ場合に、http://hiyama.example.com/blog/entry123 へGETが送られます。
これが図の状況です。

(1) 「http://hiyama.example.com/blog/entry123 へのアンカーをクリック」
(2) 「http://hiyama.example.com/blog/entry123 へGETを送る」
この2つに違いはありません。

> リンクはURLを示すもので、URLはサーバーサイドへのアクセス先を示すものなので、
> アプリケーション状態(クライアントサイド)に対してはどうやってもリンクできないかと思います。
これがまさに僕が「ちょっと違うのでは」と感じるところです。以下に、もう一度説明しますね。
(他のご指摘には異論ありません。)

> リンクはURLを示すもので、URLはサーバーサイドへのアクセス先を示すものなので、
同じURLに対して、GETとPOST(その他のメソッド)を送ったとき違う挙動を示すことが多いですよね。
ということは、「アクセスして何が起きるか」を一意的に識別するために、URLだけでは不足だということです。
URLのパス部分をリソースIDと考えることにして、「アクセスして何が起きるか」を決定する要因は:
(1) リソースID
(2) クエリーパラメータ
(3) リクエストのエンティティボディ
これらの組み合わせとなります。
(推奨はしませんが)もしパスの一部をパラメータ的に使っているなら、
(1-1) リソースID
(1-2) パスに埋め込まれたパラメータ
となります。
リクエストに対する挙動がURLだけで一意に決定されるのは、パラメータを含まないURLとGETしか使ってない場合に限られるでしょう。
これは素朴すぎて現実的なモデルとは思えません。

> アプリケーション状態(クライアントサイド)に対してはどうやってもリンクできないかと思います。
「リンク」という言葉をどのように解釈してますか?
「なんらかのID文字列があり、それを使って指し示す」ということであれば、おっしゃるとおり「アプリケーション状態にに対してはどうやってもリンクできない」です。
僕が問題にしているのは状態遷移です。クライアント側のユーザー(Webシステムのアクター)が時間順に経験する変化の系列です。
可能な変化の系列全体を有向グラフとして描いたとき、状態と状態を繋ぐ有向辺が重要だ、ということです。
クライアント側の状態ノードを繋ぐ有向辺をいきなり「リンク」と呼ぶのは、言葉の使い方としては乱暴過ぎるかもしません(ゴメンナサイ)が、
僕が問題にしている“リンク”とはそのようなものです。

サーバー側に存在すると想定されるリソースIDを繋いだグラフでは、Webシステムの動的な振る舞い、つまりユーザー(アクター)が経験するであろう事象の時系列を記述するにはまったく不十分だと思うわけです。

RikaTRikaT 2012/07/10 02:23 なるほど、仰られていることが理解できました。
以前、檜山さんの別記事で、列挙可能性について書かれていたと思いましたが、その辺りの話とも絡む話ですね。確かにRESTfulな設計では、URLだけでWebシステムの動的な振る舞いを全て表現する事はできないと思います。HTTPヘッダーやHTTPメソッドなど、様々なHTTPの仕様を図に含めないとならなくなりそうです。

>(1) リソースID
>(2) クエリーパラメータ
>(3) リクエストのエンティティボディ
後はHTTPヘッダーに含まれる文字列で、Accept-Charactorによってエンティティボディに含まれる返す言語が異なったり、Accept-Charsetによってはエラーを返すようなWeb APIもあるかもしれないですね。

>「リンク」という言葉をどのように解釈してますか?
URLによるハイパーリンク、の意でした。檜山さんの仰っているのは状態の間に引く、指向性のある線、矢印的なもの?でしょうか。そういう意味であれば、
>ハイパーリンクによりリンクされる対象はリソースではなくてアプリケーション状態
というのは納得です。リソースの"内部状態"の遷移を矢印で表すこともできるでしょうけど、リソースの遷移を繋ぐだけではあまり意味のある図にはならなさそうです。

m-hiyamam-hiyama 2012/07/10 09:10 RikaTさん、

> 檜山さんの仰っているのは状態の間に引く、指向性のある線、矢印的なもの?でしょうか。そういう意味であれば、
そういう意味なんです。
ただし、クライアント側の状態遷移の表現としての矢印を「ハイパーリンク」と呼んでしまうのは、いかにもマズかった、と反省してます。
僕にとって注目に値する矢印(=リンク)はクライアント側の状態遷移であり、それこそが「ハイパーリンク」の本質だと思ってますが、
そういう認識が一般的だとは思えないので、俺俺「ハイパーリンク」でした。

> リソースの遷移を繋ぐだけではあまり意味のある図にはならなさそうです。
はい、そういうことです。
リソースIDでラベルされたノードと、それを繋ぐ有向辺からなるグラフは描けますが、情報量が少なすぎて、ユーザー(Webシステムのアクター)が経験するであろう事象系列(クライアント側の状態遷移のパス)を推定することができないのです。
そういう大雑把な有向グラフを描いてみても、システムのトータルな挙動を掴むことは出来ない、というのが僕の経験です。
よって、もっと精密な分析をするには、最初から「クライアント側の状態遷移図を描くぞ」と決意する必要があります。
この観点から言えば、「リソースノードを結んだ図でハイパーリンクが表現できる」のような言明は受け入れられません。