【vte.cx応用】13. 規約とATOM Entryについて

今日は規約とATOM Entryの詳細について説明します。

## 規約が必要な理由

皆さん、Web APIを作るときにフォーマットを意識したことはありますか？

Qiitaの記事、[Web APIにはJSONベースのフォーマットを使おう](http://qiita.com/tkawa/items/2841e155e5b51c09ed40) で紹介されているように、JSONの構造をフラットにするとか、エンベロープで括るかとか検討しながら作っていくものだと思いますが、実際には深く考えずに開発者の感性で自由に設計しているのが現状だと思います。

それだと何がまずいか？　実はそれほどまずいことはありません。
独自のルールでお勝手APIを作っても、使うのは自分自身なのですからまず困ることはないでしょう。

ただ、[このBlog](http://blog.virtual-tech.net/2014/08/restjson.html)にも書いていますように、「適切な制約」を設けることで設計のコストが下がる」という大きなメリットが生まれることもわかっています。つまり、共通の規約に従うことで汎用的にできると同時に生産性も向上させることができる。

とりわけ、“Constraints are liberating”「制約は自由をもたらす」ことは強調しておきたい点です。

APIを公開して他人に使ってもらおうと思っているのでしたら尚更、規約（制約）は重要になってくると思います。

## 標準的な規約の欠如とATOM採用の理由

問題は、どの規約に従うかということなのですが、実はこれといって標準がないのが問題なんです。

vte.cxの基盤となっているReflexWorksでは、2007年ごろにAtom Syndication Formatを採用することにしました。当時はXML全盛の時代で、Googleなどが積極的にATOMを採用しており迷うことなく採用したのを覚えています。

しかし、JSONによるREST APIが主流となった現在ではXML/ATOMは使われません。
JSONがこれまでXMLで培ってきたセマンティック文化を破壊した結果、今は無法地帯と化しています。
もちろん、HALやJSON APIなどが存在することは承知していますが、それらが一気に標準になるとは思えないのが正直なところだと思います。

Swaggerは、RESTful APIの記述標準化を目指す「Open API Initiative」で採用されるようですが、これについても厳然とした規約があり、作り手がこの規約に合わせる必要があります。

例えば、XMLにはエンベロープがありますがJSONにはありません。もちろん、あった方が綺麗で見やすいのは確かですが、それではXMLとJSONとで意味が異なってしまいます。細かい違いですが、これもSwaggerの規約の一つといえるでしょう。(ちなみに、vte.cxでは両方にエンベロープであるfeedとentryが付きます。) 

標準に準拠させるには大きなコストがかかります。すべて規約に則って作らないといけません。
なので採用の条件としては、多くの人が利用しているのはもちろん、将来的にも廃れないものを選択すべきです。

vte.cxではATOMのJSON表現を使っていますが、それは、「JSONやXMLなどの表現にとらわれない汎用的な」リソース構造を定義するスキーマ言語を導入できたからです。

昔は標準だったATOMが今は使われていないように、Swaggerも同じ運命をたどらないとも限りません。
今流行りかけのSwaggerに対応するのも可能だとは思いますが、流行に振り回されないで互換性をなくさないことの方がより重要です。
余程のことがない限り、vte.cxでは引き続きATOMを使っていきます。

## ATOM linkの補足説明

ATOM feed/entryには必要最低限の項目だけが定義されています。
vte.cxが使用しているATOM項目と意味については[４日目の記事](http://qiita.com/takeyama/items/2ea32e60c8b9252cfe27)でも紹介していますが、ここではATOM Entryのlinkについてもう少し補足します。

### link

linkには、rel="self"、rel="alternate"、rel="via"、rel="related"、rel="next"の５種類のrelを指定することができます。

#### selfとalternate

rel="self"はEntryの参照元を示します。
rel="alternate"はaliasと呼んでいるもので、Entryの別名を示します。

つまり、Entryには複数のaliasを持つことができ、それぞれのURIで参照することができます。
Linuxのシンボリックリンクのようなものです。

例えば、以下は/barと/bazの２つのaliasを持つEntryであることを示しています。
idにはEntryの実体が入っており、通常の検索ではidと参照元のselfで同じものが入ります。（/foo で検索）

```
<entry>
    <id>/foo,1</id>
    <link href="/foo" rel="self"/>
    <link href="/bar" rel="alternate"/>
    <link href="/baz" rel="alternate"/>
</entry>
```

alias検索では、例えば、/barで参照すると以下のようになります。(参照元のselfが/barになる）
idが同じなので実体は上記と同じものが参照されていることがわかります。

```
<entry>
    <id>/foo,1</id>
    <link href="/bar" rel="self"/>
    <link href="/bar" rel="alternate"/>
    <link href="/baz" rel="alternate"/>
</entry>
```

alias検索については、[ドキュメントの別名(alias)](http://reflexworks.jp/documentation.html#taggingservice.html#R7)もご覧ください。

また、他ノードのデータ検索ができるようにaliasの機能を拡張したシャドウという機能もあります。[シャドウと他ノード検索](http://reflexworks.jp/documentation.html#taggingservice.html#R8)
これは内部的に分散ノード検索を実行しますが使い方はaliasと同じです。

#### via

rel="via"はメール送信やMobilePushなどの通知機能で使われます。
詳しくは、[ドキュメントの通知機能](http://reflexworks.jp/documentation.html#taggingservice.html#N)を参照してください。

#### related

rel="related"はリダイレクトを実行するために使います。
詳しくは、[ドキュメントのリダイレクト](http://reflexworks.jp/documentation.html#taggingservice.html#R11)を参照してください。

#### next

rel="next"はページネーションにおいて、次ページ検索のためのカーソルがある場合に使います。
詳しくは、[ドキュメントのFeed取得](http://reflexworks.jp/documentation.html#taggingservice.html#G2)を参照してください。

ということで、本日はこれでおしまいです。
明日はコンテンツマネージメントについて説明します。
それでは。