Slide 1

Slide 1 text

GraphQL "スキーマ設計基本方針"の案 その1

Slide 2

Slide 2 text

IDは型を超えてユニークなもの とする

Slide 3

Slide 3 text

リクエストユーザーのユーザー情報を取得するクエリがあると する。

Slide 4

Slide 4 text

レスポンス IDに型名と主キーの情報を入れることで、オブジェクトと1:1対 応するIDを作ることができる。 IDをURLの形にしている例があったので参考に Base64エンコードしているものもよくある

Slide 5

Slide 5 text

Node interface, Query.node を実装する

Slide 6

Slide 6 text

Node interface ユニークなIDが取れる id フィールドをもつインターフェース を Node インターフェースとする。

Slide 7

Slide 7 text

Query.node ユニークなIDから、対応するオブジェクト(ノード)を取得す る。

Slide 8

Slide 8 text

先ほど取得したユーザーのIDを使って、ユーザー情報を取得す る。

Slide 9

Slide 9 text

レスポンス IDに紐づいたデータの型が User と一致したので、 ... on User でセレクトしたフィールドが取れる。

Slide 10

Slide 10 text

IDやnodeクエリをどのように 活用するか?

Slide 11

Slide 11 text

ユーザーが自分のユーザー情報を取得する OK

Slide 12

Slide 12 text

管理者がユーザー一覧を取得する

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

一覧から選択したユーザーの情報を取得する "任意のユーザー情報を取得するクエリ"が不要になる

Slide 15

Slide 15 text

さらにユーザーに紐づいた情報を辿る ユーザーに紐づいているメールアカウント(複数可)を取得す る

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

さらにMailAccountの詳細を取得する

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

1 2 3 5 4 6

Slide 21

Slide 21 text

ユニークなIDとnodeクエリがあると 何がうれしいか?

Slide 22

Slide 22 text

GraphQLでは、オブジェクト同士が関連づけられたネットワー ク(グラフ)を表現し、その関連付けを辿ることでデータにア クセスする。

Slide 23

Slide 23 text

ユーザー一覧を取得 ユーザーを選択してその詳細情報を確認 さらにそのユーザーが使うメールアカウントの詳細情報 を確認... 前回のクエリで取得したIDとnodeクエリによって グラフの探索を再開する。

Slide 24

Slide 24 text

1 2 3 5 4 6

Slide 25

Slide 25 text

グラフを上手に探索していくためには、オブジェクトのフィー ルドから関連するオブジェクトにアクセスできるのでなければ ならない ↓ User.mailAccounts: [MailAccount] ↓ オブジェクト同士の関連付けを型レベルで記述する強制力とな る

Slide 26

Slide 26 text

その1

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

その2

Slide 29

Slide 29 text

いずれも、UserとMailAccountの関連付けが型で表現されて いない 1つ目については2回のリクエストが必要、REST APIと変わ らない

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

ルートフィールドでは、テナン トやサービス全体に関わる情報 を取れるようにする

Slide 32

Slide 32 text

ルートとなる型 = Query , Mutation , Subscription ここで言うルートフィールド = node , viewer , ...

Slide 33

Slide 33 text

先ほどの例… Query.node とinline fragmentsを使用することで、 Query.user のようなクエリを実装しなくても任意のユーザ ー情報が取れるようになっていた。 では、Queryにはほかにどのようなフィールドを生やすことに なるのか。

Slide 34

Slide 34 text

テナントやサービス全体に関わる情報 たとえば、たぶん、こんな感じになる…?

Slide 35

Slide 35 text

エラー発生時のレスポンスに注 意する

Slide 36

Slide 36 text

GraphQLでのエラーレスポンスは以下のような形になる。

Slide 37

Slide 37 text

エラーが発生したフィールドの値は null になっている それまでに解決できた値(username)は取得できている extentions に任意の情報を持たせることができる(エラ ーコード)

Slide 38

Slide 38 text

どんなフィールドを Non-Nullにするか

Slide 39

Slide 39 text

先ほどの例では、ユーザーに紐づいた2つのメールアカウント のデータ取得に失敗し、 "mailAccounts": [null, null] が返っていた。 もし User.mailAccounts の型が [MailAccount!] で、2 つのうち1つのメールアカウント取得に失敗するとどうなる か…?

Slide 40

Slide 40 text

こうなる

Slide 41

Slide 41 text

仕様書に書いてある。 https://spec.graphql.org/June2018/#sec-Errors-and- Non-Nullability https://spec.graphql.org/June2018/#sec-Combining- List-and-Non-Null Since Non-Null type fields cannot be null, field errors are propagated to be handled by the parent field. If the parent field may be null then it resolves to null, otherwise if it is a Non-Null type, the field error is further propagated to it’s parent field.

Slide 42

Slide 42 text

Non-Null型のフィールドはnullになることができないため、 フィールドエラーは親フィールドで処理されるように伝播し ます。親フィールドがnullである可能性がある場合、nullに 解決されます。それ以外の場合、Non-Null型である場合、 フィールドエラーはさらにその親フィールドに伝播されま す。

Slide 43

Slide 43 text

値の解決でエラーが発生する可能性があるフィールドは、 Nullableにしておきましょう。 そうすることで、取得できた値はそのまま使えます(F/Eがそ れを使うかどうかは別の話)。

Slide 44

Slide 44 text

エラーコードはenumで定義する

Slide 45

Slide 45 text

スキーマで定義することで、F/EとB/Eの認識の相違を防ぐこ とができる サーバーにしかわからない補足情報がある場合、それもスキ ーマで型定義しておくと良さそう(もしあれば)

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

GraphQL "スキーマ設計基本方針"の案 その2 enumはUPPER_SNAKE_CASEにする MutationのInput, Payloadは input や type としてまと める complexityを計算して、APIサーバーを保護する 保護しやすいスキーマ設計 本番環境ではintrospection, GraphiQLを無効化する