バージョン番号をURLに含めるべき「でない」理由について、 自分はどのように考えているか具体的に述べたいと思う。
見過ごせない根本的な問題
http://blog.kazuhooku.com/2014/03/web-api.html
http://yohei.hatenablog.com/entry/2014/03/12/001707
一方で、単純にCRUDに当てはまらないものはどうするんだ?RESTでCRUD4つに集約できるなんて幻想だ!なんていうのもわかる。
に同意である。 そこで述べられているように、
・拡張が容易である
・拡張時に後方互換性を破壊しない
をしっかり守り、互換性を壊すことがないようにできるだけ変更を少なくしたうえで、
互換性を壊す必要がある場合は関数名を変更する、といったような感じで概ね解決できると思う。
ただ、何というか、根本的なところで琴線に触れるものがあって、見過ごせないなあと感じている。
率直にいうと、そもそもAPIのv2を作りたくなるような状況に陥ることこそが問題ではないかと思っている。
JSONのような拡張可能なシリアライズフォーマットを用い、拡張可能な形で入出力パラメータを設計する。これは、いわゆるスキーマレスとかソフトスキーマといわれるもので、項目が変わったとしてもシステムに影響ないような仕組みである。つまり、項目が変更されても影響なければバージョン管理はそもそも必要ないというわけ。
これはJSONだけでなくXMLやMessagepackでも同じことがいえる。
メディアタイプでデータ表現を変えるという発想はReflexWorksに近いというか、そのものなんだけれども、RESTのリソースの概念では表現を変えてもデータは同じものであって、v2なんていう発想はない。 (もちろん、データが更新されたらリビジョンは上がるがAPIのバージョンに相当するものはない)
それから、私はJSONの文化大革命って呼んでいるのだが、過去にHTMLやXMLで積み上げたセマンティクスの議論が台無しになっている雰囲気があって、今回のようなAPIでバージョニングすべきかが問題になるのは当然の帰結のような気がしてしかたがない。
今さら、ATOM PUBとかいうつもりはないけれど、それにしても、勝手気ままにAPI作りがちではないか?
最悪なのは、getXXX,updateXXX というように単にエンティティに操作をつけただけの関数をモッサリ作ってる。 だから、/v2/getXXX なんて欲しくなるわけ。データこそJSONかもしれないが、これこそSOAP時代の発想じゃないか。
HTTPのGETやPOSTほど変更に強いAPIはないわけだし、RESTで単純にHTTPメソッドへマッピングして、GET|POST /XXX でいいじゃん、と思う次第。
CRUDに当てはまらないAPI
基本的にリソースは静的なデータであって、GET /XXXとすると、/XXXのデータがそのまま返る。
しかし、/XXXの結果を加工したくて、サービスとしてサーバサイドで動的にビジネスロジックを動作させたいこともある。
例えば、消費税計算関数calcがあり、デフォルトは5%であるとしよう。以下のように書くことで、calc(/XXX)を実行する。つまり、/XXXで取得した原価のフィードを関数calc()で消費税5%で計算して返す。
GET /XXX?f=calc
さらに、8%で計算するv2も定義してURLパラメータで表現する。4月以降はv2をつけて実行すればよい。
GET /XXX?f=calc+v2 あるいは、GET /XXX?f=calc&v=2 など。
つまり、URLパラメータでバージョニングすればよいという結論である。
いつのまにかURLにバージョン番号をつけるべきという結論になってしまっているが、言いたかったのはリソースはあくまで静的なものであって、リソースをCRUDする限りにおいてバージョニングは必要ないということ。
結論からいえること
また、リソースの項目の追加変更においても必要ない。唯一、必要になるのはCRUDに当てはまらない一部の動的なサービスAPIであって、それでもURLパラメータで管理すればよく、API全体をバージョニングする必要はないということ。
だから、/v2/~というように、URLにバージョン番号をつけるべきではないと思う。