とろろこんぶろぐ

かけだしR&Dフロントエンジニアの小言

GraphQL 成熟度モデル

記事の概要

この記事は、Meta 社 relay.dev チームの Jordan Eldredge 氏の Tweet で紹介された GraphQL 成熟度モデル (GraphQL maturity model) を個人的な見解を加えながら和訳した記事です。

jordaneldredge.com

GraphQL を実装する上で、どの程度 GraphQL を使いこなせているか判断するための参考になれば幸いです。

実際の成熟度モデルの和訳

最初の Tweet

私は、GraphQLの利点がまだ十分には理解されていないと思っています。ほとんどの組織では、GraphQL の提供する価値を捉えきれていません。

そこで、私は「GraphQL成熟度モデル」をスケッチしてみました。あなたの組織はどの程度成熟して(=使いこなせて)いますか? もし以下に示す13の成熟度を達成していたとしたら、よりGraphQLを評価するのでしょうか?

No. 1

1/サーバーがGraphQLをサポートしていることです。アプリケーションのモバイルとウェブの両クライアントは、サーバーのコードを変更することなく、また他のクライアントへの影響を心配したりすることなく、普通にクエリの作成、データの追加・削除ができます。

No. 2

2/ 型やフィールドはきちんとドキュメント化されていることです。GraphiQLは、インターナルな環境でインタラクティブなプレイグラウンドやドキュメントとして機能します。開発者は必要なデータを見つけることができ、何度も同じサーバー上の処理を記載する必要はありません。

No. 3

3/ GraphQL のサーバーとクライアントの両方で、それぞれの言語の型システムを統合して利用していることです。これによりネットワーク API の境界を超えた型安全性が確保されます。

No. 4

4/ スキーマをデフォルトで null 許容にするという GraphQL Working Groups 推奨のベストプラクティスを採用していることです。一般的にサーバー上で発生するフィールドのエラーは大したことがなくハンドリングできる UI のエラーです。これによりアプリの回復力(可用性?)が高まります。

No. 5

5/ Node の仕様を採用していることです。Graph のほとんどのオブジェクトが強力なIDを持ちます。クライアントは、個々のオブジェクトのデータを簡単に再取得できます。

No. 6

6/ GraphQL クライアントフレームワークが、Node 仕様の強い ID を使用して正規化された形式(キー ⇒ オブジェクト)で GraphQL のデータを保存していることです。表示上におけるデータの不整合は発生せず、クライアントのメモリ使用量も少なくて済みます。

No. 7

7/ GraphQL サーバー側でリストをモデリングするために Connections 仕様を実装していることです(ほとんどの UI は見せかけのリストです)。 GraphQL クライアントフレームワークは、どのような表示においても機能する堅牢なページネーションを提供することができます。

No. 8

8/ 各 UI のコンポーネントが、GraphQLフラグメントを使用してコンポーネントに閉じた状態でデータを定義していることです。クエリーは、コンポーネントに書かれたフラグメントから構成されます。コンポーネントは、他のコンポーネントに対する破壊的な影響を心配することなく、コンポーネント内部に閉じてデータを追加/削除することができます。

No. 9

9/ GraphQLのクライアントフレームワークが、コンポーネントのフラグメントを使って表示単位ごとに単一のクエリにまとめていることです。UIは、幾重にも重なったローディングの状態になることなく、1回でロードされ表示されます。これにより、ユーザーはあなたに感謝することでしょう。

No. 10

10/ サーバーとクライアントの両方が @-defer@-stream をサポートしていることです。UXデザイナーは、UXを向上させる場合にのみ、1行追加するだけでコンポーネント内でネストされたローディング状態を宣言的に許容することができます。

No. 11

11/ GraphQL クライアントフレームワークが、各コンポーネントのフラグメントを活用して、各コンポーネントで指定されたサブスクリプションを構築していることです。バックエンド側のストアに変更を加わると、直接影響を受けるコンポーネントのみが再レンダリングされます。これにより UI がよりレスポンシブになります。

No. 12

12/ クライアント側のアプリを開発するエンジニアが、エディターで GraphQL のランゲージサーバーを活用していることです。各フィールドは利用可能な内容でオートコンプリートされます。フィールドの上にカーソルを合わせると、ドキュメントや型を見ることができます。非推奨のフィールドは、IDEで波線や取り消し線などのが表示されます。

No. 13

13/ クライアント側のアプリを開発するエンジニアの GraphQL エディターは、フィールド/型のクリック時の定義ジャンプに対応しています。他のクライアントの関数にジャンプできるのと同様に、フィールドのサーバー実装に簡単にナビゲートすることができます。

最後のツイート

...これはまだ、今日時点で実現可能なことをなぞったにすぎず、完全なものとは思いません。

どんな技術にもコストと利点があります。しかし、その利点がより広く実現されれば、GraphQLのコストはそれほど痛くない(高くない)ものと感じられると思っています。

個人的見解や解説、補足など

筆者は JS x Relay x VSCode での開発経験が大きいので、以下はそれに偏った補足になります。

No. 1 について

これは GraphQL の実装をきちんとしているよね、という基礎的な話なので、特に補足はありません。

No. 2 について

GraphiQL は実際に開発を進める上でとても有用です。基本的には Apollo Server や Yoga Server などの GraphQL サーバーで plugin や option を設定するだけで使えるようなものなので、使える状態になっているべきです。さらに GraphQL スキーマのフィールドやクエリに対してコメントをしていれば GraphiQL でドキュメントとしても利用可能です。GraphQL スキーマにも Lint をかけておき、コメントは必須な状態にしておくと良いです。

cf. Introducing GraphQL-ESLint! – The Guild

No. 3 について

GraphQL のスキーマから GraphQL Codegen や Relay などのツールやフレームワークで型生成は行えるので、使うべきです。No. 3 まではメリットというよりは GraphQL 使う上で必須なものと言えると思います。

No. 4 について

個人的には、フィールド全てをデフォルトで null 許容にすることはなかなかないのかなとは思います。ただ UI 上では仮にエラーが起きて表示できなかったとしても、画面そのものの表示を取りやめるほどではない場合もあります。そういったケースに備えてフィールドの null 許容は、選択肢として頭に入れておくと良いと思います。

No. 5 について

Node の実装は正規化キャッシュのためにも、オブジェクトの使い道に応じて定義しておくとよさそうです。 ただ現実問題、全てのオブジェクトに一意の ID を設定するのに限界があるので、全て Node 化は難しいとは思います。

また Relay では使って当たり前の雰囲気を出しつつ、Node に関するドキュメントがそこまで充実してないので、 Node を理解するのがそもそも難しいというのも取り込まれづらい要因になっていそうです。

No. 6 について

Relay では、 Node を実装していれば特に意識することなく正規化キャッシュしてくれます。

No. 7 について

Connections も取っ掛かりづらい仕様ですが、カーソルベースのページネーションであることを理解してしまえばこれまでのオフセットベースのページネーションを包含した概念であることが理解できると思うので、一度実装してみると良いと思います。

No. 8 について

フラグメントコロケーションは、 GraphQL の代名詞とも言える機能ですね。もっと手前に出てきてもいいような。

No. 9 について

Relay では、手間がかからずフラグメント化したクエリを Persisted Query にまでしてくれるので、悩むことは少ないと思います。

No. 10 について

これは、 Tweet を読むまで deferstream が既に使える状態であることを知りませんでした...!勉強不足でした...。 ...というわけで、まだ使ったことがないので見解は特にナシ。

No. 11 について

Subscription は WebSocket や GraphQL-SSE などを用いてリアルタイムに UI に変更を加える機能です。実装コストは安いわけではありませんが、有用なケースはあると思うので、 UX の向上のために取り入れるのも良いと思います。

No. 12 について

VSCode であれば GraphQL の拡張機能と .graphqlrc の config の設定があれば動作します。 ちなみに deprecated directive は VSCode だと取り消し線ではなく波線になったと思います。

No. 13 について

こちらも VSCode であれば GraphQL の拡張機能と .graphqlrc の config の設定があれば動作します。

おわりに

以上が GraphQL 成熟度モデルの和訳と少しの解説になります。

GraphQL は難しいと捉えられることも多く、メリットよりもコストが注目されることも多々あるイメージがあります。

すべてのメリットを享受しようとせず、難しさとその代わりに得られるメリットを体系的に理解して、順々に使い慣れていくことができればと思います。

この記事が少しでもその助けになれば嬉しいです。