APIサーバー
JSON API サーバーを開発するとき、クライアントはHTTPリクエストを発信し、サーバーは応答をJSON表現のデータ構造で返す。
このようなAPIの設計について、従来はRESTがよいとされてきた。
facebookが提案するGraphQLというものが、Github API v4 に採用されるなど実績がつまれてきたので調べてみた。
REST api おさらい
Ruby on railsのリソース表現にも採用され、こうした特長がある。
-
RESTの原則
- (Uniform Interface) 情報の操作は、すべてHTTPメソッド(GET, POST, PUT, DELETE)でおこなう。
- (Addressability) リクエストのURLによって、提供する情報がひとつに定まる。
- (Stateless) サーバーは状態をもたない。
- (Connectability) 応答する情報に、別の情報へのリンクを含めることができる。
-
RESTの性質
- GETリクエストは再実行に対して安全である。
- PUT等のリクエストは再実行しても指示以上の動作をおこさない(べき等と呼ぶ)
- サーバーはリソースごとに固有のURLをもち、メソッドによって操作が決まる。
-
RESTの実際
- とはいえ、必要な情報をかき集めるためには、普通はindexなどのREST外URLも使うよ。
GraphQL api
GraphQL では、応答のデータ構造はリクエストが決定する。
RESTが取り組んできたUniform Interface、Addressability、については修正される。
-
GraphQLの原則
- あらゆるGraphQLのリクエストと、応答を引き受ける、唯一のURLを提供する。
- 仕様化されたクエリ言語で情報を請求したり、操作を請求したりする。
-
GraphQLの性質
- 個々のリクエストにあわせて通信内容を絞り込むので、最小限の通信サイズとなる。
- 必要な多数のリソースを、関連づいた形式でまとめて取得する。
- 書き込み系処理の仕様変更をサーバーで吸収しやすい。
GraphQL ⇔ REST
REST、GraphQL でアクセスするAPI サーバーを想像してみた。
![alt](http://yuml.me/diagram/plain/class/[A]<>1 a-bs *[B],[B]<>1 b-cs *[C])
※ graphql-ruby で構築した場合
このとき、開発者は下表のような量のコードを記述する。(graphql-ruby IDLが採用されると、記述はシンプルになりそう。)
単位 | GraphQL | REST | |
---|---|---|---|
config/routes.rb | 行 | 1 | 3 |
app/controllers/* | action | 1 | 5 * 3 + 1 = 16 |
app/models/* | class | 3 | 3 |
app/graphql/* | schema | 1 | 0 |
app/graphql/types/* | type | 5 | 0 |
n+1 対策 (lazy) | class | 2 | 0 |
RESTでは、同コントローラークラスのactionに処理を記述する。共通部分は private method にまとめるか、 modelに追い出すリファクタリングをしていく。
比べてGraphQLでは、Fieldのresolveに処理を記述する。共通部分は主にmodelへ追い出すリファクタリングをする。
また、n+1回DB問い合わせをしてしまう問題をチューニングするため、lazy_resolve インターフェースに従うキャッシュを実装する。
GraphQL 導入方法
Ruby on Rails へ GraphQLを導入するには
gem "graphql"
gem "graphql-batch"
gem "graphiql-rails"
rails generate graphql:install --batch --schema=#{AppName}Schema
rails g graphql:function #{function_name}
rails g graphql:mutation #{mutation_name}
rails g graphql:loader
書き方
参考になるサンプル。 https://github.com/joe-re/sample-graphql-on-ruby
Schema、query type、 mutation type を構築する。
実務では、それらが持つfieldは、のtype定義は、modelごとにファイルを用意して管理するとよい。
- Schema
- query
- field
- type
- argument
- resolve
- field
- mutation
- field
- type
- argument
- resolve
- field
- query
参考
http://graphql-ruby.org/
https://github.com/graphql/graphiql
http://mgiroux.me/2015/getting-started-with-rails-graphql-relay/