Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQLのあまり知られていない魅力 (スキーマの表現力編) / domain model...
Search
adwd
February 25, 2022
Programming
6.3k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphQLのあまり知られていない魅力 (スキーマの表現力編) / domain modeling with GraphQL Schema
adwd
February 25, 2022
More Decks by adwd
See All by adwd
RxJSで状態を管理する / state management by RxJS
adwd
1
1.3k
Savkin先生から学んだぼくの考えた最強のAngularアプリアーキテクチャ / The best Angular application architecture
adwd
1
1.2k
create-react-app-introduction
adwd
7
2k
React/Redux Introduction
adwd
17
5.3k
Other Decks in Programming
See All in Programming
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
330
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
140
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
220
共通化で考えるべきは、実装より公開する型だった
codeegg
0
250
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.5k
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
520
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
210
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
480
act1-costs.pdf
sumedhbala
0
230
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
130
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
260
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
320
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
97
6.7k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
390
The Mindset for Success: Future Career Progression
greggifford
PRO
0
420
Bash Introduction
62gerente
615
220k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
The agentic SEO stack - context over prompts
schlessera
0
850
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.2k
Transcript
GraphQLのあまり知られていない魅力 (スキーマの表現力編) ZOZO Tech Talk #4 - Webフロントエンド×新規事業 株式会社ZOZO
計測プラットフォーム本部 計測システム部 西田 雅博 Copyright © ZOZO, Inc.
© ZOZO, Inc. 株式会社ZOZO 計測プラットフォーム本部 計測システム部 西田 雅博 GraphQL+Reactを極めたい Webフロントエンドエンジニア
Rustもやりたい 2
© ZOZO, Inc. 目次 1. GraphQLとは 2. 一般的に知られているGraphQLのメリット 3. たまたま実感した予想外のGraphQLのメリット
4. こんなGraphQLスキーマです 5. GraphQLスキーマの表現力から得られたメリット 6. まとめ 3
© ZOZO, Inc. GraphQLとは 4
© ZOZO, Inc. GraphQLとは 5 • Meta(Facebook)が開発したクライアントが指定 したデータの形でサーバーがレスポンスを返す クエリ言語 •
https://graphql.org/ • https://spec.graphql.org/October2021/
© ZOZO, Inc. 一般的に知られていそうなGraphQLのメリット • 画面に必要なデータを取得するのに1度のリクエストで済む • リクエスト、レスポンスに静的型が付くのでTypeScriptなどとの相性がいい • GraphiQLやApollo
Sandboxといったプレイグラウンドが便利 • Apollo FederationやSchema Stitchingなどマイクロサービスを束ねる仕組みがある ついでにデメリットも • すべてが POST /graphql になるのでキャッシュや監視のやり方が変わる • クライアント、サーバーともに実装が変わったりと学習コストが必要 6
© ZOZO, Inc. たまたま実感した予想外のGraphQLのメリット • ある新規事業の小さいサービスをREST APIからGraphQLに移行しようとしている • それほど複雑なQuery, MutationがないのでGraphQL特有のメリットはあまりなく、練習くらい
になると思っていた ところが、 • GraphQLスキーマの表現力が高く、REST APIでは表現しきれなかったサーバーとクライアン ト間のドメインロジックが表現できた 7 次のスライドからZOZOMAT for Handsというとある小さいサービスと、そのサー ビスのドメインロジックを表現できたGraphQLスキーマを紹介します
© ZOZO, Inc. 8 • 足のサイズを測ってピッタリのサイズの靴を買えるZOZOMATの指輪版
© ZOZO, Inc. 9 • 足のサイズを測ってピッタリのサイズの靴を買えるZOZOMATの指輪版 • マットの上に手をおいて、音声のガイドに従ってスマホのカメラで色んな 方向から手を撮影すると最適な指輪のサイズを出してくれる •
まだ一般リリースしてなくてこっそりやってます
© ZOZO, Inc. ZOZOMAT for Handsの測定はステップや状態が多い ユーザーに色んな角度から手をスマホで撮影してもらう必要 がある 1.
真上から撮影して左右どっちの手か、マットが平たく置い てあるかなどを判定する 2. マットの色に沿っていろんな角度から手を撮影する 3. 最後に真上からもう一度撮影して完了 このステップごとにサーバーと通信していて、クライアントは今 どのステップにいるのか、次はどのステップかを知る必要があ る 10
© ZOZO, Inc. ZOZOMAT for Handsはエラーがたくさんある • 最初の真上から撮影するとき
◦ 人差し指と中指の間隔が開きすぎている ◦ カメラが手に近すぎる • いろんな角度から撮影しているとき ◦ 指定した色の方向から撮影していない ◦ カメラの角度が高すぎる • などなど • それぞれ対応した音声ガイドを再生するのでエラーハン ドリングが重要 11
© ZOZO, Inc. こんなGraphQLスキーマです 12
© ZOZO, Inc. type Mutation { """ TODOを追加します """ addTodo(text:
String!): Todo } type Todo { id: ID! text: String! status: TodoStatus! foo: FooUnion! } union FooUnion = BarType | BazType | QuxType GraphQLスキーマの基本的な読み方 • Mutation: 実行でデータが変化する操作 ◦ RESTでいうとPUT/POST/DELETE ◦ QueryはGET • addTodoミューテーション ◦ NonNullなStringを引数にとって ◦ NullableなTodoを返す • type Todoで型を宣言 ◦ id, text, status, fooフィールドがある ◦ どれもNonNull • statusはTodoStatus enum • FooUnionは3つのうちいずれかになる 13 enum TodoStatus { TODO DONE }
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted どんなGraphQLスキーマになったか ※説明用に簡略化していますが実際のスキーマと基本的には同じです 14
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 15 ダブルクォート3つで囲んだところはdescription コメントのようなものだけどMarkdownも使えるれっきとしたドキュメント GraphQLの型で表現しきれないビジネスロジックは無理せずdescriptionを活用する
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 16 descriptionに書いてあるとおりの処理を行うprocessSessionミューテーション ※GraphQLでファイルアップロードは現状できないので、graphql-multipart-requestを使います
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 17 processSessionミューテーションの結果はセッションの途中、失敗、完了の3種類
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 18 processSessionミューテーションの結果は セッションの途中、失敗、完了の3種類
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 19 セッションの途中の場合は次の測定の指示 enum CaptureInstruction { TOP BLUE # ... }
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 20 測定ステップ失敗の場合はその理由 enum ProcessSessionFailure { CAMERA_PITCH_TOO_LOW DISTANCE_TOO_CLOSE # ... }
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 21 測定完了の場合は結果を取得するためのID (結果を出すのに数秒かかるので終わったことだけ通知する)
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted ここまでのまとめ • processSessionを繰り返し使って計測を進める • processSessionは3パターンの結果を返す • 計測途中、失敗、完了それぞれ次の動作に必要な情報 が入っている 22
© ZOZO, Inc. type Query { """ 計測が完了したセッションを取得します。 """ session(id:
ID!): Session } type Session { id: ID! analysis: SessionAnalysis! } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定結果を取得する session クエリ 23
© ZOZO, Inc. type Query { """ 計測が完了したセッションを取得します。 """ session(id:
ID!): Session } type Session { id: ID! analysis: SessionAnalysis! } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定結果を取得する session クエリ 24 測定の結果が分析途中、分析完了、分析失敗の3パターンにな ることがわかる。 それぞれの型の中身は省略するが、途中なら数秒後クエリを再 実行、完了なら結果を表示、失敗ならエラー表示すれば良いこ とがわかる
© ZOZO, Inc. type Mutation { processSession(sessionId: ID!, image: Image!):
ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted type Query { session(id: ID!): Session } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定の一連の流れがスキーマから読み取れる 25
© ZOZO, Inc. GraphQLスキーマの表現力から得ら れたメリット 26
© ZOZO, Inc. ドメインモデリングともいえる議論が活発にできた • 最初はREST APIをそのまま移したようなスキーマだったがGitHubのPR上で100件近いコメン トで盛んな議論ができた🔥 27
© ZOZO, Inc. ドメインモデリングともいえる議論が活発にできた • 最初はREST APIをそのまま移したようなスキーマだったがGitHubのPR上で100件近いコメン トで盛んな議論ができた🔥 • 紹介したスキーマは割とシンプルですが原型はかなり違った
◦ Union、EnumといったGraphQLの型システムの恩恵 ◦ 今回は使ってないですがディレクティブも強力です • 以前のREST APIのときは入社間もないこともあって正直言ってあまりドメインを詳細まで理 解できていなかったが、この議論とGraphQLスキーマからよく理解できた 28
© ZOZO, Inc. DDDのドメインモデリングにも使えるのではないか • 先日読んだDomain Modeling Made Functionalという本はF#の型システムを利用してドメイン モデリングしていた
• GraphQLくらいの型システムでも実現可能と思える • マイクロサービスが境界づけられたコンテキストに該当するならそのコンテキストが外部に提 供する能力を可読性高く表現できる…気がする • GraphiQLやApollo Studioで動作が確認しやすいこと、スキーマのドキュメント性が高いことも ドメインエキスパートにやさしいのでは 29
© ZOZO, Inc. まとめ • 小さなサービスにGraphQLを導入した • 予想していなかった効果として、スキーマの表現力によってドメインに関する議論が盛んに 行えた •
GraphQLおすすめです! 30
None