リソースの考え方
Web アプリケーションや Web サービスを RESTful に設計するときに、まず大切になるのはリソース設計(リソースモデリング)だと考えています。私が自分でサービスを開発するときは、そのサービスでどんなリソースを提供するのか、をまず考えるようにしています。
リソースの設計は、関係データベースのスキーマ設計のように系統立ててまとまった手法は存在しません(情報アーキテクチャは一つのスタートポイントになるのでは、と考えています)。
今回は以前、社内向けにまとめたリソース設計に関する文書を再構成してみました。何かのヒントになれば幸いです。
#余談ですが、RESTful Web Services を初めて読んだとき、 表現の選択のところで出てくるフォーマットリストとほとんど同じものが9章に出てきてちょっとびっくりした思い出があります。
概要
Web サービスや Web アプリケーションの設計を行うときは、どのようにリソースを分割していくかが重要となります。本文書では、REST (Representational State Transfer) におけるリソースについて簡単に振り返り、新しくリソースを作成する際のヒントを示します。
リソースの考え方
REST の定義に従えば、リソースは情報の断片です。
しかし、それではあまりに抽象的すぎるので、ここではもう少し具体的な定義をします。
リソースはたとえば以下のようなものです。
- 東京の天気予報
- 新花巻駅の写真
- Dijkstra 著 “Go To Statement Considered Harmful“
- 私の最近のブックマーク
これはすべて Web 上にあるデータです。そう、リソースとは Web 上にあるデータを少し抽象化したものだと考えても構いません。
概念的には Web 上にないデータでもリソースと捉えることは可能ですが、無理にはやらない方がよいでしょう。たとえば「人」というリソースを考えるのは面白いですが、残念ながら物理的な人は Web 上でデータとして存在し、やりとりされることはありません。
Web 上に存在するのは「人」ではなくて「人のブログ」だとか「人の写真」でしかないのです。
リソースと URI
Web 上のリソースの大きな特徴の一つとして、「全てのリソースが URI を持つ」ということが挙げられます。リソースが URI を持つことでリソース同士をリンクさせることができるのです。
リンクは Web を考える上で非常に重要です。リンクされていない Web ページは Web 上に存在しないも同然だからです。
リソースとリソースの表現
リソースは情報、あるいは Web 上のデータだと述べました。このリソースをサーバ・クライアント間で転送するときのデータ形式のことをリソースの表現といいます。
一つのリソースでも複数の表現を持つことがあります。
たとえば2006年10月10日の東京地方の天気予報、というリソースを考えてみましょう。このリソースの URI はたとえば以下のようになります。
http://weather.example.com/20061010/tokyo
HTTP クライアントがこのリソースを GET するとこのようになります。
リクエスト
GET /20061010/tokyo HTTP/1.1 Host: weather.example.com
レスポンス
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<html>
<head>
<title>2006年10月10日の東京の天気</title>
</head>
<body>
<h1>2006年10月10日の東京の天気</h1>
<p>晴れ</p>
</body>
</html>
ここでサーバからクライアントに返されているのは、 2006年10月10日の東京地方の天気予報、というリソースの「HTMLによる表現」です。
このリソースは「晴れ」という情報を持っていますが、その表現形式は HTML であっても、 XML であっても PDF であっても画像であっても音声あっても映像であっても構いません。重要なのはこのリソースが「2006年10月10日の東京地方の天気予報」を表しているということです。
HTTP の Accept リクエストヘッダを使うと、欲しい表現の形式の優先度を明示的に指定することもできます。以下の例は Atom 形式の表現を HTML 形式の表現よりも高い優先度でリクエストしている例です。
リクエスト
GET /20061010/tokyo HTTP/1.1 Host: weather.example.com Accept: application/atom+xml;q=0.9,text/html;q=0.5
レスポンス
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<entry xmlns="http://www.w3.org/2005/Atom">
<title>2006年10月10日の東京の天気</title>
<updated>2006-10-10T00:00:00Z</updated>
<author><name>foo bar</name></updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">晴れ</div>
</content>
</entry>
リソースと URI は1対1の関係ではないため、複数の URI が同一のリソースを指すこともできます。たとえば、上記の天気予報の URI
- http://weather.example.com/20061010/tokyo
と、HTML 表現や Atom/PDF 表現を明示的に参照する URI
- http://weather.example.com/20061010/tokyo.html
- http://weather.example.com/20061010/tokyo.atom
- http://weather.example.com/20061010/tokyo.pdf
は同じ「2006年10月10日の東京地方の天気予報」というリソースを指しています。
リソース表現と選択肢
上述のように、一つのリソースを提供するのにも、いくつもの表現の選択肢が考えられます。ここでは、代表的な表現の形式とその特徴を簡単に説明します。
- HTML/XHTML
- Web 上で最も一般的な形式
- ブラウザで表示できるので、人間が読める
- ここで挙げた形式の中で最も自由度が高い
- 逆にいうと最もあいまいな形式
- microformats(XHTML)
- イベント情報、レビュー、コンタクト情報といったあらかじめ決められたデータ形式を XHTML に埋め込むための規格
- XHTML の class, rel 属性を利用するだけなので、他の形式との親和性が高い
- XHTML のあいまいな部分をある程度制限し、人間が読むだけではなくプログラムからも扱いやすい形式
- XHTML と併用可能
- microformats.org で定義されていないものは一般性に欠ける
- Atom feed/entry (RFC 4287)
- HTML が人間用ならば、Atom はプログラム用の代表形式
- XML なので HTML よりもあいまいな部分が少い
- contents 要素などに XHTML を入れることができる
- タグの拡張が自由
- ある程度のメタデータ(ID、タイトル、日付、著者)はあらかじめ決められている
- AtomPub との親和性が高い
- 画像(gif/jpeg/png/pdf)
- これらの形式でしか表現できないリソースも多い
- HTML の img 要素からリンク可能
- JSON/JSONP
- Javascript から利用しやすい呼出しやすい
- Javascript 以外のプログラミング言語のバインディングもある
- データ表現に優れている
- 配列、データ型、ハッシュなどの表現も可能
- XML(XHTML/Atom) よりも記述がコンパクト
- HTML の script 要素からリンク可能
- Javascript から利用しやすい呼出しやすい
Web API とリソース
ここまでずっと Web API という言葉を出さずにリソースについて説明してきました。
いわゆる Web API というのは、 URI と HTTP を使ってリソースを提供し、編集・更新する仕組みです。すべてのリソースは URI で特定でき、HTTP を使ってさまざまな表現形式でクライアントとサーバの間のやり取りが行われます。
HTTP ではメソッド情報は固定されています。オブジェクト指向設計でクラスの振る舞いを考えるように、リソースの振る舞いを考えても HTTP メソッドは追加できません。リソースに新しいメソッドを追加したくなったら、別のリソースを用意するのが正しい考え方です。このように、HTTP を使った Web API の設計では HTTP メソッドを限定したり、拡張したりすることはなるべく避けるべきです。
この HTTP メソッドを固定する考え方を統一インターフェースと呼びます。すべてのコンポーネント間で、ただ一つのインターフェースを使うことで、世界規模での相互運用性が初めて確保されるのです。
Web API は、URI と HTTP を使ってリソースを操作する仕組み、と言い換えることもできます。
まとめ
Web API を設計する上で、最も重要なのはリソースの設計です。リソースの設計は大きく次の二つに分けられます。
- リソースの URI の設計
- リソース表現の設計
リソースは抽象的な概念ですが、今我々がブラウザから使っている Web をあてはめて考えると非常にわかりやすくなると思います。ブラウザを人が操作しているところが、プログラムにかわるということです。
リソース設計で悩んだときは、そのリソースの HTML 表現を考えてみましょう。
