記事の概要
この記事は、Meta 社 relay.dev チームの Jordan Eldredge 氏の Tweet で紹介された GraphQL 成熟度モデル (GraphQL maturity model) を個人的な見解を加えながら和訳した記事です。
GraphQL を実装する上で、どの程度 GraphQL を使いこなせているか判断するための参考になれば幸いです。
実際の成熟度モデルの和訳
最初の Tweet
私は、GraphQLの利点がまだ十分には理解されていないと思っています。ほとんどの組織では、GraphQL の提供する価値を捉えきれていません。
そこで、私は「GraphQL成熟度モデル」をスケッチしてみました。あなたの組織はどの程度成熟して(=使いこなせて)いますか? もし以下に示す13の成熟度を達成していたとしたら、よりGraphQLを評価するのでしょうか?
I believe the benefits of GraphQL are fundamentally under-realized. Most organizations fail to capture much of the value it can provide.
— Jordan Eldredge (@captbaritone) 2023年4月7日
In thought I’d sketch out a "GraphQL maturity model". How mature is your org? Would you appreciate GraphQL more if you were at 13?
🧵/ 15
No. 1
1/サーバーがGraphQLをサポートしていることです。アプリケーションのモバイルとウェブの両クライアントは、サーバーのコードを変更することなく、また他のクライアントへの影響を心配したりすることなく、普通にクエリの作成、データの追加・削除ができます。
1/ Your server is supports GraphQL. Your application clients, both mobile and web, are generally able to independently craft their own queries, adding and removing data, without needing to modify server code or worry about impacting other clients.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 2
2/ 型やフィールドはきちんとドキュメント化されていることです。GraphiQLは、インターナルな環境でインタラクティブなプレイグラウンドやドキュメントとして機能します。開発者は必要なデータを見つけることができ、何度も同じサーバー上の処理を記載する必要はありません。
2/ Your types and fields are well documented. GraphiQL acts as an internal interactive playground and documentation for your API. Developers can find the data they need and don’t replicate server behavior in multiple places.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 3
3/ GraphQL のサーバーとクライアントの両方で、それぞれの言語の型システムを統合して利用していることです。これによりネットワーク API の境界を超えた型安全性が確保されます。
3/ You are using a GraphQL server and client which both integrate with their respective languages’ type systems. You now have type safety that spans your network API boundary.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 4
4/ スキーマをデフォルトで null 許容にするという GraphQL Working Groups 推奨のベストプラクティスを採用していることです。一般的にサーバー上で発生するフィールドのエラーは大したことがなくハンドリングできる UI のエラーです。これによりアプリの回復力(可用性?)が高まります。
4/ You have adopted the GraphQL Working Groups recommended best practice of making your schema nullable by default. Individual field errors encountered on the server generally manifest as small, handleable, UI errors. Your app’s resilience increases.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 5
5/ Node の仕様を採用していることです。Graph のほとんどのオブジェクトが強力なIDを持ちます。クライアントは、個々のオブジェクトのデータを簡単に再取得できます。
5/ You adopt the Node specification. Most objects in your graph have a strong ID. Your clients can easily refetch data about individual objects.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 6
6/ GraphQL クライアントフレームワークが、Node 仕様の強い ID を使用して正規化された形式(キー ⇒ オブジェクト)で GraphQL のデータを保存していることです。表示上におけるデータの不整合は発生せず、クライアントのメモリ使用量も少なくて済みます。
6/ Your client GraphQL framework uses the strong IDs of the Node specification to store GraphQL data in a normalized form (key ⇒ object). You never have data inconsistency issues between surfaces, and your client uses less memory.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 7
7/ GraphQL サーバー側でリストをモデリングするために Connections 仕様を実装していることです(ほとんどの UI は見せかけのリストです)。 GraphQL クライアントフレームワークは、どのような表示においても機能する堅牢なページネーションを提供することができます。
7/ Your server implements the Connections specification for modeling lists (most UIs are glorified lists). Your client GraphQL framework is able to provide robust pagination that works for all your surfaces.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 8
8/ 各 UI のコンポーネントが、GraphQLフラグメントを使用してコンポーネントに閉じた状態でデータを定義していることです。クエリーは、コンポーネントに書かれたフラグメントから構成されます。コンポーネントは、他のコンポーネントに対する破壊的な影響を心配することなく、コンポーネント内部に閉じてデータを追加/削除することができます。
8/ Each of your UI components defines its own data dependencies using a GraphQL fragment. Queries are composed from these fragments. Components can add/remove data locally without having to worry about breaking anyone else.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 9
9/ GraphQLのクライアントフレームワークが、コンポーネントのフラグメントを使って表示単位ごとに単一のクエリにまとめていることです。UIは、幾重にも重なったローディングの状態になることなく、1回でロードされ表示されます。これにより、ユーザーはあなたに感謝することでしょう。
9/ Your client GraphQL framework composes your components’ fragments together into a single query per surface. Your UI loads in a single paint without dozens of loading states. Your users thank you.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 10
10/ サーバーとクライアントの両方が @-defer
と @-stream
をサポートしていることです。UXデザイナーは、UXを向上させる場合にのみ、1行追加するだけでコンポーネント内でネストされたローディング状態を宣言的に許容することができます。
10/ Your server and client both support @-defer and @-stream. UX designers can declaratively opt into nested loading states with one line of code directly in their components only where it improves user experience.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 11
11/ GraphQL クライアントフレームワークが、各コンポーネントのフラグメントを活用して、各コンポーネントで指定されたサブスクリプションを構築していることです。バックエンド側のストアに変更を加わると、直接影響を受けるコンポーネントのみが再レンダリングされます。これにより UI がよりレスポンシブになります。
11/ Your client GraphQL framework leverages each component’s fragment to build targeted subscriptions for each component. Changes to the store result in only the directly affected components rerendering. Your UI is more responsive.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 12
12/ クライアント側のアプリを開発するエンジニアが、エディターで GraphQL のランゲージサーバーを活用していることです。各フィールドは利用可能な内容でオートコンプリートされます。フィールドの上にカーソルを合わせると、ドキュメントや型を見ることができます。非推奨のフィールドは、IDEで波線や取り消し線などのが表示されます。
12/ Your client engineers are making use of a GraphQL language server in their editors. Fields autocomplete with available data. They can hover over fields to see documentation/types. Deprecated fields render as struck through in their IDE.
— Jordan Eldredge (@captbaritone) 2023年4月7日
No. 13
13/ クライアント側のアプリを開発するエンジニアの GraphQL エディターは、フィールド/型のクリック時の定義ジャンプに対応しています。他のクライアントの関数にジャンプできるのと同様に、フィールドのサーバー実装に簡単にナビゲートすることができます。
13/ Your client engineers’ GraphQL editor integration supports click-to-definition for fields/types. They can navigate to the server implementation of a field as easily as they can jump to another client function.
— Jordan Eldredge (@captbaritone) 2023年4月7日
最後のツイート
...これはまだ、今日時点で実現可能なことをなぞったにすぎず、完全なものとは思いません。
どんな技術にもコストと利点があります。しかし、その利点がより広く実現されれば、GraphQLのコストはそれほど痛くない(高くない)ものと感じられると思っています。
... this is still just scratching the surface of what's possible today, and I don't think we're near a saturation point.
— Jordan Eldredge (@captbaritone) 2023年4月7日
Every technology has its costs and benefits. But I think GraphQL's costs would feel less painful if its benefits were more broadly realized.
個人的見解や解説、補足など
筆者は 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 を読むまで defer
や stream
が既に使える状態であることを知りませんでした...!勉強不足でした...。
...というわけで、まだ使ったことがないので見解は特にナシ。
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 は難しいと捉えられることも多く、メリットよりもコストが注目されることも多々あるイメージがあります。
すべてのメリットを享受しようとせず、難しさとその代わりに得られるメリットを体系的に理解して、順々に使い慣れていくことができればと思います。
この記事が少しでもその助けになれば嬉しいです。