GraphQL非ヌルフィールドを使用する場合

GraphQLのnull以外のフィールドの予期しないコストのいくつかを学びます。

GraphQL型システムでは、すべての型がデフォルトでnull許容です。つまり、 Int のような型は、任意の整数( 1 2 など)または null を取ることができます。値がないことを表します。ただし、GraphQL型システムでは、任意の型を -nullにすることができます。これは、その型が null 値を生成しないことを意味します。 null以外のタイプを使用する場合、常に値があります。 GraphQL non-nullフィールドは、タイプがnon-nullであるGraphQLフィールドです。

G raphQLのnull以外のフィールドは、最初はすばらしいように見えるかもしれません。結局のところ、それらは常に特定のフィールドを持つことを保証します。ただし、null以外のフィールドを使用すると、GraphQLスキーマの展開が難しくなり、フィールドがnull可能である場合に返される可能性のある重要なデータが失われるような方法で小さなエラーが伝播する可能性があります。この投稿では、スキーマを設計するときに情報に基づいた選択を行えるように、null以外のフィールドの予期しないコストについて説明します。これらのコストを検討する前に、UI開発者の観点からnull以外のフィールドの利点のいくつかを詳しく見てみましょう。

null以外のフィールドは、データが常に存在することを静的に保証するため、非常に強力なツールです。 null許容でないフィールドからクリーンな静的型を生成できることは非常に魅力的です。たとえば、次のクエリを考えてみましょう。

このクエリのすべてのフィールドがnull以外の場合、クエリに対して次のようなフロータイプを生成する可能性があります。

ただし、すべてのフィールドがnull許容の場合、フロータイプは次のようになります。

最初の型は自分で作成する型と同じように見えますが、2番目の型は、レンダリングに使用できる適切なデータがあることを保証するために、多くのランタイム型チェックを必要とします。 (JavaScriptのように、入力せずに動的言語を使用している場合でも、どのフィールドがnullになる可能性があるかを知っておくと便利です。)このようなnull許容フィールドは、UI開発者にとって明らかなコストがかかります。

ただし、null以外のフィールドを使用することには明らかでないコストがいくつかあり、長期的にはnull可能なフィールドのコストよりも高くなる可能性があります。ただし、コストを検討する前に、GraphQL言語でのnull以外の型の履歴とセマンティクスについて説明しましょう。

null以外の型のセマンティクス

FacebookのGraphQLの最初のバージョンは、null以外のフィールドをまったくサポートしていませんでした。 すべてのフィールドはnull可能であり、フィールドをnull以外としてマークする機能が追加されたのは、仕様のオープンソースのみでした。

GraphQL仕様をオープンソース化した後でも、null許容フィールドがデフォルトであることに気付くでしょう。一方、null以外の型は、仕様の2級市民です。フィールドをnull以外としてマークするには、バン文字()を追加する必要があります。

最近のほとんどの型付き言語が反対であることを考えると、これは最初は奇妙に思えるかもしれません。 FlowやRustなどの型付き言語を見ると、デフォルトではすべての型がnullではないことがわかります。開発者は、タイプがオプションの場合、タイプチェッカーに明示的に通知する必要があります。たとえば、Flowでnull可能な文字列を定義するには、?string 、Rust: Option< String> 、Haskell: Maybe String

この規則がGraphQLで反転するのはなぜですか?これらの最新の型付き言語とは異なり、GraphQLは単一のスキーマからさまざまな異なるクライアントにサービスを提供することを目的としています。 Flowでタイプを作成すると、そのタイプのすべてのコンシューマーを制御します。ただし、GraphQLでは、同じAPIに依存する多くのチームが存在する可能性があり、さらに重要なことに、GraphQLの一般的な「バージョンレスAPI」の性質を考えると、入力の決定を元に戻すのは困難です。

さらに、null以外のフィールドのコストの一部を考えると、null許容フィールドはデフォルトとして意味があります。これらのコストの最初のものは…

null以外のフィールドは、スキーマの進化を困難にします

アプリケーションに新しい機能を追加しようとしていて、スキーマを変更する必要がある場合、最初はnull可能であれば、いつでもフィールドをnull以外にすることができます。 GraphQLクライアントは常にnullを予期していたため、これによって破損することはありません。クライアントがnullを取得しない場合、nullを処理するコードは実行されません。ただし、null以外のフィールドをnull可能にすることは決してできません。 GraphQLクライアントのコードは、特定のフィールドからnullが返される可能性があることを知らなかったため、最初にnullに遭遇したときに 壊れます。

これにより、将来スキーマを進化させることがはるかに困難になります。スキーマを設計するときは、「これをnullにしたいと思う可能性がどれほどありそうにない場合でも、 もっともらしい宇宙はありますか?」と自問することが重要です。答えが「はい」の場合(または質問が複雑すぎて答えられない場合)、おそらくGraphQLのデフォルトを維持し、フィールドをnull許容にすることを検討してください。気が変わったら、いつでもフィールドをnull以外にすることができます。

フィールドをnull以外にしたことを後悔する可能性がある将来のケースには、次のものがあります。

null以外のフィールドは、小さな障害が大きな影響を与えることを意味します

これはnull以外のフィールドのそれほど明白な欠点ではありませんが、それでも考慮する必要があります。 null以外のGraphQLフィールドでエラーが発生すると、そのエラーは最初のnull可能フィールドまで伝播されます。これは、単一のフィールドに制約される可能性のある小さなエラーが、有用なデータであった可能性のあるものを一掃することになることを意味します。これが実際のアプリケーションでどのように機能するかを次に示します。

すべてが正常に実行されている場合、このクエリは次を返します:

ここで、画像サービスが悪い日を過ごしており、2番目のユーザーに画像を返すことができないとしましょう。 null許容フィールドを使用すると、応答は次のようになります。

ここでは、エラーが発生した正確な場所に説明的なエラーがあります。ただし、 imageURL がnull以外の文字列だった場合はどうなりますか? imageURL:String!で定義されています。次に、エラーが伝播し、2番目のユーザーのすべてのデータを飲み込みます。そのデータを使用してユーザーを部分的にレンダリングすることはできたかもしれませんが、現在はできません。

インテリジェントなGraphQLクライアントを使用している場合、 imageURL は別のクエリから自動的に更新された可能性がありますが、2番目のユーザーからのすべてのデータが失われました。

ただし、null以外の型が本当に好きで、 imageURL をnull以外にするだけでなく、すべてのユーザーが users 配列もnullではありませんでした。したがって、クエリレベルの users フィールドを users:[User!] として定義します。これは無害に見えますが、nullが伝播するとどうなるか注意してください。

ユーザーの配列全体が消去されます。エラーを1か所で処理する代わりに、スキーマを介して1つのエラーが伝播しました。これは、レンダリングするデータがないことを意味します。

この例では、null以外のフィールドが1つあることに気付くでしょう。 id id がnullの場合、通常はこのエラー伝播動作が必要になるため、通常は id をnull以外にするのが理にかなっています。

結論

null以外の型の利点がUI開発にとって十分に大きい場合は、UI開発者がGraphQLでグローバルにではなく、ローカルでnull以外として必要なフィールドをマークできるGraphQLLodashのようなGraphQLクエリトランスフォーマーを検討してください。スキーマレベル。おそらく、 @nonNull のようなディレクティブを使用します。これにより、すべてのクライアントのnull許容フィールドのセマンティクスを維持しながら、単一の製品開発者が自分でnull以外の決定を行うことができます。

覚えておいてください。GraphQLスキーマのnull以外は非常に強力なツールですが、予期しないコストが発生します。 null以外のフィールドの作成を検討している場合は、次のように自問する必要があります。「このフィールドがnullであっても、このタイプをレンダリングしたいというもっともらしいシナリオは、いつの時点でもプラットフォーム上にありますか?」答えが「はい」の場合、null以外のタイプのコストがメリットを上回る可能性があります。もちろん、場合によっては( id フィールドの場合のように)null以外の不変条件の利点は、とにかくnull以外にするのが理にかなっているほど強力です。その決定はあなたとあなたのAPI消費者次第です。それ以外の場合、質問が複雑すぎて短期間で回答できず、それほど重要ではない場合は、null許容フィールドを選択することをお勧めします。