Web APIの設計指針についての補足
先日初めて、自分が書いたブログの記事、Web API設計指針を考えたがはてブでバズるという経験をしました。たくさんの方に読んでいただけたというのは非常にうれしいことです。ただ、設計指針には根拠を書かなかった箇所が多く補足したいところが出てきたため、以下の内容について根拠などを書いていきたいと思います。
- バージョニングについて
- RESTfulについて
バージョニングの設計・実装について
以下の指針を書きました。
APIにはバージョンをつける。
vと整数のバージョン番号をURLにつける。
バージョンは整数。マイナーバージョンは作らない。
例) http://api.example.com/v1/users
上記指針をRailsで実装する場合には、バージョンを上げるときにはコントローラごと分けるようにしています。
ただ、少々前の話になりますが、こんな記事がありました。
Web APIのバージョニングの方法として、エンドポイントでバージョンを分けるよりもリクエストヘッダなどにバージョン情報を入れて限局分岐で実装するがよいのではなかろうかという話です。
限局分岐にするメリットとして大きなところは以下があると思います。
- バージョンを上げるとき、下回りのライブラリをアップデートする際にコピペプログラミングをしなくてよく、将来的に両方のバージョンのAPIをメンテする必要がない。
- 限局分岐にすると積極的にAPIの改善をしていくことが可能。コントローラでバージョンを分けると、結局バージョンをなかなか上げることができない。
しかし、私としては、基本的には限局分岐は避けたいという考えで、コントローラでバージョンを分けてしまうという指針としています。
限局分岐を避けたい理由は以下です。
- 限局分岐にすると、動いているソースを直す以上デグレの可能性がある。ただ、Railsなどのアップデートでソース修正を入るないといけないような場合はバージョン違いの同じ箇所を直す必要が出てくるという話はまさにその通りだと思う。しかし、限局分岐にしたところでも、いずれにせよその可能性は発生する。
- テストがちょっと書きにくい。
- エンドポイントで分けるとブラウザからテストしやすい(爆)。
- 限局分岐は、分岐が増えてくるとソースを読むのが難しくなってくる。
個人的には最後の理由が重要だと思っています。というのも、以前の仕事のミドルウェア開発で、バージョンによる動きの違いをひたすら限局分岐的に対応していたことが非常に辛かった記憶があるためです。あとで開発に入った人が、どのバージョンでどういう動きをするのかを把握するのも難しくなります。
また上記記事には、コントローラを分けた際の問題が指摘されています。
せっかくコントローラを分けても、モデル層やJSON生成層その他で発生した非互換な変更には無力なので、結局ぼくがやってるのと似たような仕組みでMVCを超えたバージョンの受け渡しが必要になります。
この問題に対する対処としては、モデルやサービス層などで非互換を出さないように対応します。つまり、モデルやサービス層でバージョンの意識・分岐はせず、分岐が必要になる状況になれば新しいメソッドなりクラスなりを作ります。こうすると、(理論的には)既存の動いているAPIに影響はないということになります。
上記の理由から、バージョン違いはエンドポイント、コントローラを分ける方針としています。
しかしこの方針だと、バージョンアップするタイミングはほぼやってこないというのはまさにその通りで、APIの継続的な改善を行うことは難しいことは事実です。なかなか難しいところです。
RESTfulについて
RESTには必ずしもこだわらず、あくまで利用側の利便性を重要視した設計とする。
1つの作業を完結するために複数回のアクセスを必要とするようなAPIの設計はChatty APIと呼ばれる。これはネットワークのトラフィックを増加させ、クライアントの処理の手間を増やす。
と書きましたが、こういう方針にするとついついRESTは無視して変なエンドポイントにしがちになる傾向があり、最近は出来る限りRESTfulにする方向にしています。
そこで、オーケストレーション層という話も出てきます。
特にモバイルアプリ向けAPIのアーキテクチャとして、オーケストレーション層を入れるというやり方をしているところもあるようです。以下のような感じでしょうか。
- バックエンドにRESTfulな単純にデータを返すだけのAPIを用意。
- 上記APIを利用、マッシュアップして、クライアントに適したAPIを提供するオーケストレーション層を用意。
参考URL:http://d.hatena.ne.jp/heavenshell/20140310/1394453328
この場合、バックのAPIとしてはRESTfulなものとなります。
OSやデバイスごとに大きく異なるUIの場合や、見せる情報が違ってくる場合にはこのようなやり方は有力になってくると思いますが、OS間でほぼ同じUIを実現しようとするような場合では、オーケストレーション層を作るコストに合ったメリットはない場合も多いのではないかと思います。
そうなるとChatty APIを防ぐためにはどうしてもRESTfulからちょっと離れてくる部分は出てくるとは思っていますが、出来る限りRESTfulな分かりやすいAPIとするよう心がけています。
以上、補足記事でした。
弊社ではWeb APIを活用したWebアプリケーションやスマートフォンアプリケーションの開発に力を入れています。よろしければ会社ページもご覧いただければ幸いです。