ジャバ・ザ・ハットリ
Published on

GraphQLを最速でマスターするための意識改革3ヶ条

Authors
  • avatar
    ジャバ・ザ・ハットリ

GraphQL をサーバー側とクライアント側とで実装してみて得た意識すべきポイント3つについて。

  • ひとつのエンドポイント
  • バージョン無し
  • できるだけ薄く

この3つを意識して実装するのとそれが無いのとでは実装スピードが何倍か違うと思う。特に REST 脳な人の場合。

GraphQL は使い所さえあえばめちゃくちゃに有用で面白い。しかもGraphQL の公式サイトはとてもわかりやすく説明されている。その辺のブログ記事よりもよほど洗練されていて、技術に関してはここ以外に読む必要はほぼ無い。

しかし GraphQL を使いはじめた当初はなんか妙にコーディングが進まなかった所があった。その原因はずっと RESTful でやってきた REST 脳の意識から GraphQL へと変換できていなかったことだった。GraphQL と REST は設計思想が異なるので、意識を変える必要がある。その意識さえ変えれば GraphQL に難しいところなんて無く、とてもカンタンに実装できてしまう。公式サイトに技術内容がどんなに分かりやすく書かれていても、このポイントを絞って意識を変えることに注力していなかったら「あれ??今まではこうだったのに、なぜだ?」となってしまうのだ。

そもそも GraphQL ってなに?となっている人はこことか公式サイトを読んでください。

GraphQL を書いてみた話 - emahiro/b.log
GraphQL に関するメモ - ushumpei’s blog
GraphQL を使ってみた - kakts-log

以下はその GraphQL の概念は分かっているという前提で書く。

【意識改革1】 ひとつのエンドポイント

GraphQL にエンドポイントはひとつしかない。REST のように GET api/v1/users POST api/v1/users/:id とか一切無い。どんなリクエストも全て/graphql に向けて飛んでくる。GraphQL のクエリ言語がそういった処理を全て吸収してくれるからだ。クライアント側を実装していて「えーっとこのリクエストはどこに投げればいいんだっけ?」と思う度に、いやいや「どこ?」とか考えてる時点でそれ REST 脳だ、と自分で訂正していた。

個人開発したウェブアプリを GraphQL で実装していた時にある箇所のキャッシュとデータベース側の処理を2種類に分ける必要があった。そこで通常の処理を/graphql で受けて、その他の処理を別のエンドポイント(例えば/graphql2 とか)で受ける設計を考えた。今から考えてもバカなデザインだったと思う。こんなことをすると GraphQL のメリットをちっとも活かせないし、メンテナンス性が著しく下がる。後から query や Type が変更になった際にいちいち2つのエンドポイントとその挙動について考えなければならない。個人でやってたのでクライアント開発者とサーバー開発者の間でやりとりする必要は無く、自分の脳内で2役やって終わりだったが、あれをチームでやってたら、エンジニア同士の間でムダな話し合いが増えていたことが分かる。

GraphQL のメリットはクライアントーサーバー間で「この型でいきましょう」と決めただけで実装にかかれるところにある。後は欲しい情報を欲しい時にリクエストするだけで完了する。
公式サイトにはサラっとしか書いていないが「ひとつのエンドポイント」はとても重要なことなのだ。

【意識改革2】 バージョン無し

GraphQL は基本的にバージョンレス。つまり REST のようなバージョンという概念は無い。REST でやってるプロジェクトはapi/v1/... からバージョンがあがるとクライアント側の実装と呼吸を合わせて、せ~のでapi/v2/... とかを作ってリリースしていた。
理論上はうまくいくはずなんだけど常にこれが頭痛の種になる。だが GraphQL にバージョンは無い。/graphql というエンドポイントで v1 も v2 も無くずっとそのままだ。

これが REST 脳だった私には不安だった。「え?バージョン無し???一応は念の為に付けとこうかな?」みたいに考えた。しかしこの質問と答えで気が付いた。「REST の API になぜ v1 やら v2 とバージョンがあるのか?」答えは「破壊的な変更があって、その度にバージョンを上げる必要があるから」と。
つまりは「GraphQL にすれば破壊的な変更は無いのでバージョニングする必要がない」となる。
クライアントが欲しい情報をリクエストして、そのままレスポンスを返す GraphQL では基本的に変更をかけても破壊的ではない。今まであった field を削除するとかは破壊的かもしれないが GraphQL では add-only approach を推奨している。つまり加えるのみ。

なので今回作った rails のルートは Best Practice にのっとり
graphql POST /api/v1/graphql
とかではなくて
graphql POST /graphql
としている。清々しい。対外的にも「バージョンは無いからな」と宣言することにもなる。
今まで RESTful で API のバージョンを上げることの痛みをずっとガマンしてきた人なら、この versionless API という発想は気に入っていただけるだろう。

【意識改革3】 できるだけ薄く

GraphQL の作者 Lee Byron 氏も言うように「なんでもできる GraphQL だが、GraphQL はできるだけ薄く保つのがいい」と。Lee Byron 氏の公演ビデオはとても示唆に富んだビデオで参考になる。そんな中で一番はこの「できるだけ薄く保て」という箇所だった。
実装していけば認証やらセッション管理やらありとあらゆる処理が GraphQL を通して行われる訳だが、それらを GraphQL 内でやってしまわないこと。それらの処理をするのに適したクラスが必ずあってそっちでやるべき。
GraphQL の責務と役割は query(RESTful の GET)と mutation(POST もしくは PATCH)だけであって、それ以外は無い。したがって resolve ->(obj, args, ctx)の中にロジックがあったら、その責務はどこが持つべきか考えてそこに移すべき、ということだ。
これはアプリのソースコードが大きくなればなるほど効いてきた。「薄くしといてよかったなー」と。

以上が GraphQL を最速でマスターするための意識改革3ヶ条でした。

動く GraphQL の実例

こちらが GraphQL と Rails、React+Redux を使って個人で開発したウェブアプリです。
エンジニアの集合知を図解する SNS「node-node-node」デスクトップ版
PC でしか見れませんが、ぜひ感想をお聞かせください。

情報ノードはパラっと開いて、グリグリとドラッグできる訳でして、こうして階層構造の技術リンクをマッピングしていけば理解しやすいかな、と。