アーキテクチャパターンとしてのRESTを整理する

#1.　はじめに

　この記事の目的は、Webサービス設計における**制約集合**である**「REST」アーキテクチャパターンについての知識を整理すること**です。設計そのものについては、軽く手順を触れるにとどめます。
　カリフォルニア大学アーバイン校の大学院生であった**Roy Fielding**が2000年の博士論文にまとめたREST。**リソース指向アーキテクチャ（ROA）**と関連して言及されることの多いRESTですが、いざ説明を求められると存外言葉に詰まるものです。
　将来、誰かに教える機会が訪れたときのためにも、知識を整理しておきます。

#2.　アーキテクチャとアーキテクチャパターン

　RESTはアーキテクチャパターンです。アーキテクチャではありません。

　こう言われると、そもそもの言葉の定義に戻ることをしないと頭が混乱します。アーキテクチャとアーキテクチャパターンの違いは何なのだろうか…？と。

　まずは具体例を表で整理してみます。

| 抽象化レベル       |例            |
|:-----------------|:--------------------------|
| 実装             |Apache,Nginx,Chrome,Firefox,Edge,...        |
|アーキテクチャ           |HTTP,URI,HTML,ブラウザ,サーバ,プロキシ,...  |
|アーキテクチャパターン   |REST,MVC,クライアントサーバ,インタプリタ,...|

　実装レベルから抽象度を上げて、かけのぼった先に「制約」としてのアーキテクチャパターンが構えています。
　**実装は、いわばソースコードの集合**。C,C++,Rust,Python,その他さまざまな言語で記述されたプログラムのことです。**アーキテクチャは、そうしたソースコードの集合を、全体における役割レベルに抽象化したもの**と言えます。たとえば、ApacheであればWebという全体におけるサーバという役割、Chromeであれば、Webという全体におけるブラウザという役割です。
　そして、**アーキテクチャパターンは役割に依存しないさまざまな役割に適応可能な制約の集合**です。

　つまり、アーキテクチャが特有の問題領域の構成要素としてのポジションに縛られているのに対して、アーキテクチャパターンは、それら構成要素に対して1対1の関係にはなりません。
　アーキテクチャパターンから見て、アーキテクチャは1対多の関係にあります。

#3.　アーキテクチャパターンとしてのREST

　アーキテクチャとアーキテクチャパターンを抽象度の違いの文脈において整理したところで、RESTアーキテクチャパターンの特徴を整理したいと思います。

##RESTはクライアント/サーバモデルから派生した

　**RESTは複数のアーキテクチャパターンを組み合わせて構築した複合アーキテクチャパターン**です。これは、アーキテクチャパターンが「制約」であることを考えれば、不自然なことではありません。制約を組み合わせて、複合の制約を構築することは直感的にも自然に映るかと思います。

　では、どのように制約を組み合わせていくのかというと、まず**ベースとなるのはクライアント/サーバモデル**です。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/188787/af6dfb12-1118-51f3-c027-46a09cb885ea.png)

　これに5つの制約を加えていきます。

#####(1)　ステートレスサーバ

　直訳すると「状態のないサーバ」ですが、ここでの状態とは**クライアントのアプリケーション状態**のことを指します。つまり、サーバはクライアントのアプリケーションが現在どのような状態にあるのかを保持しません。

#####(2)　キャッシュ

　**一度取得した情報を、鮮度や利用頻度に応じてクライアント側で使い回す方式**をキャッシュと呼びます。
　キャッシュを利用することの最大のメリットは、通信回数を減らすことで処理時間を短縮することです。ただし、キャッシュの情報が古く信頼性に欠ける場合もあります。　

#####(3)　統一インタフェース

　RESTのなかで最も特徴的なものの一つが統一インタフェースです。**リソースに対する操作を厳しく制限します**。
　たとえば、HTTPの文脈で言えば、リソースに対する操作はGET,POST,PUT,DELETEといった8つのメソッドに制限されます。一見すると柔軟性を損なう制限に思えますが、実はこれこそがさまざまなクライアントからの要求に応えるために必要なシンプルさの強制として欠かせないものです。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/188787/f0251909-9768-f919-1493-97cfb682d38a.png)

#####(4)　階層化システム

　統一インタフェースという制約を課すことで、通信をする際に「相手がどのような役割をもっているか」に依存しない、統一された通信方式でリクエストを送ることができます。その結果、システム全体における構成要素を階層化することが容易になります。

#####(5)　コードオンデマンド

　コードオンデマンドとは、**プログラムをサーバからダウンロードして、クライアント側でそれを実行する**パターンです。JavaScriptやJavaアプレットなどがこれに該当します。

　以上、クライアント/サーバモデルに対して(1)～(5)の制約を組み合わせることで、厳密な定義におけるRESTが構築されます。
　しかし、実際のWebにおいては、ステートフルを実現するためのCookie利用によるセッション管理が行われています。RESTの原則には違反していますが、実践の世界において「標準」の定める仕様をすべて満たすことはなかなかに難しいものがあります。
　そのため、どこまでREST原則を満たせているかをレベル0~3に分けて評価する、といった物差しも存在しています。

#4.　RESTをWebに適用する

##スコープ情報とメソッド情報

　Webサービスの動きを見るうえで有用な概念があります。それは、スコープ情報とメソッド情報です。

　**スコープ情報とは、クライアントがデータセットのどの部分に対する操作を要求しているのかを指し示す情報**のことです。私たちが慣れ親しんでいる形式では、URIパスにスコープ情報が配置されます。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/188787/78d7901c-5319-c218-a6b4-39c3e82ecc4c.png)

　**メソッド情報とは、データの操作に関する情報**です。上の例で言えば、HTTPメソッドのGETがメソッド情報に該当します。

　これら2つの概念をもとにRESTful Webサービスを考えると、スコープ情報をURIパスに乗せ、メソッド情報をHTTPメソッドに乗せています。下のキーコンセプトを先取りすると、ResourcesとActionsがそれぞれスコープ情報とメソッド情報に結びつきます。

##キーコンセプト

　さて、RESTful Webサービスを設計するうえで理解しておかなければならないコンセプトがあります。それは以下の3つの概念です。

- Resources
- Representations
- Actions

####(1) Resources

　RESTにおける「S(State)」の部分です。
　
　リソースとは、**Web上に存在している、名前を持ったありとあらゆる情報**のことです。東京駅の写真、北海道の明日の天気、沖縄の台風情報、あなたのブックマーク、ポッドキャストなど、すべてがリソースです。

　**悩ましいのは、「名前」をどう付けるかが設計者に一任**されていて、これといった絶対に正しいと断言できる名付けはありません。サービス内容、クライアントの需要など、さまざまな観点からリソースの洗い出しをしなければなりません。

　たとえば、レンタル自転車サービスを考えてみます。ざっと思いつくシステムが抱えるリソースとしては

- ユーザ
- 自転車
- 駐輪場
- ロケーション

などを挙げることができます（このほかにもあるでしょう）。

　先に述べたスコープ情報として、リソースはURIパスに配置されます。

####(2) Representations

　RESTにおける「RE(REpresentation)」の部分です。

　直訳すると「表現」です。**表現の主な目的は、リソースの状態を伝えること**にあります。また、**リソースの状態とは、リソースに関するありとあらゆる情報の集合**です。

　たとえば、レンタル自転車サービスの駐輪場リソースの場合

- 収容できる自転車の台数
- 駐輪場の位置（緯度、経度）
- 貸出可能な自転車のID
- 予約されている自転車のID

など、さまざまな状態を想定することができます。**同じ「駐輪場」という名付けをされたリソースでも、サービス内容によって想定される状態には違いが生まれます**。

　代表的な表現形式を表にまとめます。

| 分類      | 表現形式       | 
|:-----------------|:------------------|
| XML形式             |XTML,Atom,独自XML |
| 軽量フォーマット形式          |JSON/JSONP,YAML,CSV |
| マルチメディア形式             |画像(GIF,JPEG,PNG),映像(MPEG,WMV,MOV),マルチページ画像(PDF,TIFF) |

　最近では、軽量フォーマットであるJSONによりリソース状態を表現してやり取りすることが主流です。クライアントは、レスポンスボディに含まれるリソース状態を表現形式に応じて取り出します。

####(3) Actions

　RESTにおける「T(Transfer)」の部分です。

　直訳すると「行動、振る舞い、働き」です。これは、**クライアントがリソースに直接アクセスすることができない代替として、リソースに対する操作（行動、振る舞い、働き）を要求**することを指します。

　たとえば、レンタル自転車サービスの駐輪場リソースに対して

- 駐輪場のリストを「見る」
- 駐輪場の特定の自転車を「予約する」
- 予約していた自転車を「キャンセルする」

など、リソースの状態に対する何らかの操作を想定することができます。

　先に述べたメソッド情報として、ActionsはHTTPメソッドに集約されます。

| 処理 | HTTPメソッド|
|---|---|---|
| 登録 | POST | 
| 取得 | GET | 
| 更新 | PUT | 
| 削除 | DELETE |  

他にもHTTPメソッドはありますが、基本的なRESTful Webサービスで使用するのは、上記4種のHTTPメソッドによるメソッド情報の伝達です。

#5.　RESTful Webサービスの設計

　「はじめに」で述べたように、設計については、手順のみを示します。

1. Webサービスで提供するデータを特定する
2. データをリソースに分ける
3. リソースにURIで名前を付ける
4. クライアントに提供するリソースの表現を設計する
5. リンクとフォームを利用してリソース同士を結びつける
6. イベントの標準的なコースを検討する
7. エラーについて検討する

　詳しくは、書籍「RESTful Webサービス」などを参照するといいかと思います。

#6.　まとめ

　Webサービス設計において、もはや常識としての扱いになりつつあるRESTですが、詳しく説明を求められたときに私は困りました。

　RESTに基づいて設計されたWeb APIを「利用する立場」から見ると「なるほどなるほど、こんな感じね」と中途半端な理解でも使えてしまいますが、それを設計する立場になると、半端は許されません。

　アーキテクチャとアーキテクチャパターンの違い、RESTを構成する制約集合、RESTful Webサービスのキーコンセプトなど、知識を改めて整理するうえで重要な視点が得られました。


#参考資料
[書籍：Webを支える技術](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%E3%80%81URI%E3%80%81HTML%E3%80%81%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus/dp/4774142042)
[書籍：RESTful Webサービス](https://www.amazon.co.jp/RESTful-Web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-Leonard-Richardson/dp/4873113539/ref=sr_1_1?s=books&ie=UTF8&qid=1541242311&sr=1-1&keywords=restful+web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9)
[Webサイト：How to design a RESTful API architecture from a human-language spec](https://www.oreilly.com/learning/how-to-design-a-restful-api-architecture-from-a-human-language-spec)