【3/24@オンライン開催】エイチーム×レバレジーズ フロントエンド勉強会 https://ateam.connpass.com/event/276968/
での発表資料
# 技術
GraphQL, TypeScript, ADT, 代数的データ型, Union type, Apollo Client, エラーハンドリング
代数的データ型を活用したGraphQLスキーマの設計レバレジーズ株式会社 野中柊2023/03/21
View Slide
GraphQLのエラーハンドリングでつらいところ
HTTPステータスコードが200 OKで返される
エラーがすべてerrors内に格納される
Requiredなフィールドでもエラーとなるとnullで渡ってくる
クライアントライブラリによって挙動が違う
ApolloClient- ApolloErrorにラップされる- クエリに含まれるフィールドの一部がエラーを起こすとクエリ全体が失敗する- errorPolicyで変更可能https://www.apollographql.com/docs/react/data/error-handling/#graphql-error-policies
Relayエラーにアクセスできない!公式がエラーにアクセスしたかったらフィールドの結果にエラーを含めろと言及しているhttps://relay.dev/docs/guided-tour/rendering/error-states/#accessing-errors-in-graphql-responses
urql- CombinedErrorにラップされる- ApolloErrorと同じような構造- クエリに含まれるフィールドの一部がエラーを起こしてもそれ以外のフィールドは値にアクセスできるhttps://formidable.com/open-source/urql/docs/basics/errors/
スキーマからどんなエラーが返されるのかが読み取れない
スキーマからどんなエラーが返されるのかが読み取れない- このスキーマで返されうるエラーは?
スキーマからどんなエラーが返されるのかが読み取れない- このスキーマで返されうるエラーは?- ValidationFailed- EmailDuplicated- PasswordNotConfirmed
スキーマからどんなエラーが返されるのかが読み取れない- このスキーマで返されうるエラーは?- ValidationFailed- EmailDuplicated- PasswordNotConfirmed返されそうなだけで本当に返されるかは分からない(重複OKなシステムかもしれない)
実装を自分の目で確かめるしかない
それ以外にも...
DatabaseConnectionClosedConnectionTimeoutSQLErrorOutOfMemory
じゃあどうするか?
代数的データ型を活用してスキーマの表現力を強化しよう!
代数的データ型とは?
代数的データ型とは?- データ型の一種で、既存のデータ型を組み合わせて新しいデータ型を定義するための機能- 大きく分けて直和型(sum type)と直積型(product type)からなる
ハンドリングすべきアプリケーションエラーとシステムエラーを区別する
- このスキーマで返されうるエラーは?- ValidationFailed- EmailDuplicated- PasswordNotConfirmedハンドリングすべきエラーを区別する→ アプリケーションエラー。ハンドリングしてユーザーに適切なアクションをとってもらうべき
DatabaseConnectionClosedConnectionTimeoutSQLErrorOutOfMemory→システムエラー。ユーザーにはどうしようもない
ハンドリングすべきアプリケーションエラーをスキーマで表現する
型生成ライブラリを使うと__typenameをタグとしたタグ付きユニオン型が生成されるので網羅性チェックがしやすくなる→実行時エラーを減らせる
__typenameはGraphQL specificationで定義された標準のメタフィールドなので依存しても問題無い
是非快適なスキーマ設計を!
参考文献- Production Ready GraphQL- https://book.productionreadygraphql.com/- GraphQL Specification- https://spec.graphql.org/June2018/- GraphQLスキーマ設計の勘所- https://speakerdeck.com/yukukotani/graphql-schema-design-practice