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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
今さら聞けない .NET CLI
htkym
0
180
What's New in Android 2026
veronikapj
0
250
FDEが実現するAI駆動経営の現在地
gonta
2
270
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
350
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
0
1.7k
React本体のコードリーディング
high_g_engineer
1
140
Foundation Models frameworkで画像分析
ryodeveloper
1
600
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
120
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.5k
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
180
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
450
テーブルをDELETEした
yuzneri
0
140
Featured
See All Featured
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
The Spectacular Lies of Maps
axbom
PRO
1
890
Six Lessons from altMBA
skipperchong
29
4.4k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
170
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1.1k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
So, you think you're a good person
axbom
PRO
2
2.1k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
ラッコキーワード サービス紹介資料
rakko
1
4.3M
Done Done
chrislema
186
16k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.5k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
230
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