Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
SwiftUIとGraphQLでプロダクトの継続的な破壊に立ち向かう
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
たまねぎ
September 19, 2021
Programming
3k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SwiftUIとGraphQLでプロダクトの継続的な破壊に立ち向かう
iOSDC2021 の発表資料です
たまねぎ
September 19, 2021
More Decks by たまねぎ
See All by たまねぎ
個人への依存を、AIで分散させる
chocoyama
0
27
AIのAIによるAIのための出力評価と改善
chocoyama
3
1k
[FlutterKaigi2024] Effective Form 〜Flutterによる複雑なフォーム開発の実践〜
chocoyama
1
14k
iOSDC2023:聴いて話すiOS 現実世界の「音」との連携
chocoyama
1
460
ハードウェア対応のリアル.pdf
chocoyama
0
140
20分でわかる!速習resultBuilder(iOSDC 2022)
chocoyama
7
4.1k
SwiftUIっぽくした話
chocoyama
1
770
Other Decks in Programming
See All in Programming
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
520
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
150
気持ちぃ〜角丸 Squircle
ryu1013
0
330
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
190
dotNET_vulnclicker_intro.pdf
deka_morita
0
150
Rでドレミ/Do-Re-Mi_with_R
florets1
0
130
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
Kotlinの15年とServer-Side Kotlin
n_takehata
1
160
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
900
Domain-Driven Transformation
hschwentner
2
2.3k
あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期
hasutosasaki
1
1.2k
AmebaブログはKMPから卒業します
kmars0605
0
220
Featured
See All Featured
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Design in an AI World
tapps
1
360
The Invisible Side of Design
smashingmag
301
52k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
My Coaching Mixtape
mlcsv
0
360
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
Tell your own story through comics
letsgokoyo
1
1.1k
Bash Introduction
62gerente
615
220k
Exploring anti-patterns in Rails
aemeredith
4
540
Rails Girls Zürich Keynote
gr2m
96
14k
Transcript
ɹɹ ©︎ hey, Inc SwiftUIとGraphQLで新規プロダクトの継続的な破壊に立ち向かう ヘイ株式会社 テクノロジー部門 モバイルアプリケーション本部 STORES レジ
iOSエンジニア 横山 拓也(@_chocoyama) iOSDC2021
ɹ ɹ 自己紹介 横山 拓也 Yokoyama Takuya @_chocoyama(Twitter) 2013.04 ヤフー株式会社入社 2019.12 ヘイ株式会社入社
ɹ ɹ CD
ɹ ɹ CD Continuous Delivery? Compact Disk? Creative Director? Career
Development? Cash Dispenser?
ɹ ɹ Continuous Destruction(継続的な破壊) ※ Ωϟονʔͩͱࢥ͚ͬͯͬͨͩͰɺͲ͜ʹఆண͍ͯ͠ͳ͍ݴ༿Ͱ͢
ɹ ɹ アプリケーションの継続的な破壊 改善・変更 (破壊) フィードバック Ұ࡞ͬͯऴΘΓͰͳ͘ɺ ৗʹ࡞ͬͨͷΛյ͠ͳ͕ΒɺΑΓྑ͍ͷΛࢦ͢ • UIの変更
• APIの変更
ɹ ɹ STORES レジ • 実店舗で使うPOSシステムを提供するiPadアプリ • 初期実装から変更がなかった画面はほぼ0 • 「実装→フィードバック→修正」のサイクルを
何度も高速に実行 • リリースまでに少なくとも3回ほど フルリニューアルしている
ɹ ɹ STORES レジの概要
heyが提供するSTORESプラットフォームの中の新しいプロダクト ネットショップと1つになった新しいPOSレジアプリ
ɹ ɹ 主な機能 • お会計 • 決済手段管理 • 精算 •
商品・在庫管理 • ネットショップ連携 ϨδΞϓϦ ϨγʔτϓϦϯλʔ ΩϟογϡυϩΞʔ STORES ܾࡁ όʔίʔυϦʔμʔ
ɹ ɹ 技術スタック • フレームワーク:SwiftUI, Combine • APIクライアント:Apollo-iOS(GraphQL) • SDK:STORES
決済SDK
ɹ ɹ 破壊(変更)への対応
ɹ ɹ 変更に対応していく必要性 変更 Ձ ࣮ ֬ೝ ϦϦʔε ユーザーに価値を与え続けるには、変更は避けられない ࢼߦࡨޡ
ܧଓతͳվળ ϑΟʔυόοΫ ϑΟʔυόοΫ
ɹ ɹ 変更に対応しやすい → ユーザーに価値を届けやすい 変更に対応していく必要性
ɹ ɹ SwiftUI
ɹ ɹ SwiftUIの強み • 宣言的シンタックスで シンプルな記述ができる • Previewを活用して
高速にUIの確認ができる
ɹ ɹ UIKitとの比較 1.レイアウト変更時の修正 2.表示の確認
ɹ ɹ 1. レイアウト変更時の修正 ᶃ DescriptionϥϕϧΛআ ᶄ Ձ֨දࣔͷฒͼͱҐஔมߋ
ɹ ɹ UIKit + AutoLayout 1.不要なViewを削除 2.Viewが消えたことによる不整合を修正 3.位置変更するViewのAutoLayout貼り直し 4.Outlet接続関連のコードを削除 আ
Ҡಈ
ɹ ɹ SwiftUI ① 削除 ② VStackの 外に移動 ③ HStackを削除、
Textの順番を逆に Before After
ɹ ɹ レイアウト変更のしやすさ UIKit+AutoLayout SwiftUI 依存ファイル 多い 少ない 修正ステップ 複雑
単純 安全性 クラッシュの恐れ コンパイラで保証 特有のスキルが必要 素早く安全に対応可能
ɹ ɹ 表示の確認 •「UIの変更→表示確認」のサイクルの速さは、開発効率に直結する •複数の表示パターンがあるUIの場合、特に確認コストがかかる
ɹ ɹ なんか違う… UIKit + AutoLayout •表示が実行時と異なる場合がある •確認はアプリを起動して対象画面に遷移する •1度に1パターンしか確認できない •修正と起動のサイクルを繰り返す可能性がある
このパターン はOK 全部確認 できた! मਖ਼ɾىಈ मਖ਼ɾىಈ मਖ਼ɾىಈ
ɹ ɹ SwiftUI + Xcode Preview •アプリの起動が必要ない •修正内容が即時で確認できる •任意の状態を再現したPreviewの実装を残せる •実装とPreviewを1対多の状態にできる
•(コードだけでも表示イメージがしやすい) 一気に 全部確認 できた! मਖ਼ɾىಈ
ɹ ɹ SwiftUI + Xcode Preview
ɹ ɹ 表示確認のしやすさ UIKit+AutoLayout SwiftUI アプリの起動 必要あり 必要なし パターンごとの確認 毎回起動
1度のPreview実行 継続的な利用 できない できる 高コスト 低コスト
ɹ ɹ デザインシステムに則った 共通UIライブラリを作成 STORES レジでの変更への取り組み •デザインチームが独自のデザインシステムを構築 •アプリデザインはこれをベースに画面設計 変更に耐え得る 仕組みとして
ɹ ɹ デザインシステム = デザイン原則をまとめたスタイルガイドやその実装などの仕組み 以下のような価値を生む • 一貫性のあるIFでユーザー体験を向上 • デザイナーとエンジニア間の共通言語を確立
• 局所最適されたデザインを抑制し、デザイン・開発コストを削減 デザインシステムとは
ɹ ɹ 共通UIコンポーネントの例 ※ Preview༻ͷViewΛ࣮ߦ࣌ʹݺͼग़ͯ͠ɺUIΧλϩάͷΑ͏ͳػೳΛ࡞͍ͬͯ·͢
ɹ ɹ •汎用的に使えるUIを切り出し •→ 切り出し単位はデザインシステムに合わせるだけ •デザイナーとエンジニアの画面構築工程が揃う •→ パーツを組み合わせるだけで画面ができる •アプリ内 SwiftPackageManager
で対象コンポーネントを管理 •→ 依存の切り出し •→ ビルドやPreview実行の高速化 共通UIライブラリの作成 σβΠϯγεςϜʢ໊শඇެ։ʣ σβΠϯγεςϜʢ໊শඇެ։ʣ
ɹ ɹ 実装 σβΠϯ γεςϜ໊ දࣔύλʔϯΛ PreviewͰཏ σβΠϯ γεςϜ໊ σβΠϯ
γεςϜ໊ σβΠϯ γεςϜ໊ σβΠϯ γεςϜ໊ σβΠϯ γεςϜ໊ ※ σβΠϯγεςϜ໊ඇެ։
ɹ ɹ 利用 σβΠϯ γεςϜ σβΠϯ γεςϜ σβΠϯ γεςϜ →
UI作成のコストが激減 σβΠϯ γεςϜ σβΠϯ γεςϜ σβΠϯ γεςϜ σβΠϯ γεςϜ
ɹ ɹ •レイアウトの変更が容易 → 壊しては作るといった繰り返しを気軽にできる •UIの表示確認を効率的にできる → 実装スピードが上がるだけでなく、継続的なメンテナンスにも活用できる
SwiftUIの変更しやすさ UI関連の変更にコストがかからない
ɹ ɹ GraphQL
ɹ ɹ GraphQLとは •API用のクエリ言語 •スキーマによってIFの型が厳密に決まっている
ɹ ɹ REST APIとの比較 GraphQL REST 型付け 強い 弱い エンドポイント
1つ 複数 取得リクエスト Query GET 更新リクエスト Mutation POST/PUT/ PATCH/DELETE
ɹ ɹ GraphQLの強み 1.取得するデータをクライアントが決められる 2.少ないリクエストで複数のリソースにアクセスできる
ɹ ɹ 1. 取得するデータをクライアントが決められる ϦΫΤετ Ϩεϙϯε Ұ୴શσʔλΛऔಘͯ͠ɺඞཁͳͷ͚ͩ͏ → 必要なデータだけ取得する
ɹ ɹ 2. 少ないリクエストで複数のリソースにアクセスできる Φʔμʔৄࡉը໘ アイテム情報 を追加したい
ɹ ɹ REST API の場合 Orders Items APIリクエストが増える Orders itemIds
ɹ ɹ REST API の場合 Orders Items APIリクエストが増える Orders itemIds
追加の通信処理が必要になり、実装が複雑化する OrdersAPIͷ݁ՌΛݩʹɺ ItemsAPIΛୟ͖͢ OrdersAPIΛୟ͚ͩ͘
ɹ ɹ GraphQL の場合 Orders Items APIリクエストが増えない Orders itemIds
ɹ ɹ GraphQL の場合 Orders Items APIリクエストが増えない Orders itemIds 取得したいデータを追加で指定するだけ
ɹ ɹ GraphQL の場合 Orders Items APIリクエストが増えない Orders itemIds 取得できるデータが増えるだけ
ɹ ɹ GraphQL の場合 Orders Items APIリクエストが増えない Orders itemIds 同時に複数のQueryを投げられる
ɹ ɹ STORES レジでの変更への取り組み 1.APIに変更が入ったことの自動検知(独自実装) 2.APIのIFとなるSwiftコードの自動生成(Apollo-iOSの機能を活用)
ɹ ɹ 1. APIに変更が入ったことの自動検知(独自実装) Appエンジニア 想定したデータが取得できません BEエンジニア ドキュメントの更新漏れてました BEエンジニア API完成しました
Appエンジニア APIがエラーになります BEエンジニア 変更の共有忘れてました 人力での変更管理には限界がある ケース1 ケース2
ɹ ɹ 1. APIに変更が入ったことの自動検知(独自実装) 旧スキーマ ファイル 新スキーマ ファイル App BE
旧スキーマ ファイル 新スキーマ ファイル ࠩνΣοΫ 自動でSlackに変更通知 →共有漏れや不正な定義の参照を防ぐ GitHub Bitrise
ɹ ɹ 2. APIのIFとなるSwiftコードの自動生成(Apollo-iOSの機能を利用) スキーマ ファイル BE クエリ ファイル スキーマ
ファイル ੩తղੳ Swiftコードを自動生成 →BEとAppでAPI定義が同期される Local Apollo GitHub
ɹ ɹ •取得したいデータが増えても「追加リクエスト不要」で「IFの型が自動生成される」 → 意図した変更に対応しやすい •API側の変更をシステム的に追従可能なので、人力のコミュニケーションに頼る必要がない →意図していない変更にも対応しやすい データ関連の変更にコストがかからない
GraphQLの変更しやすさ
ɹ ɹ •SwiftUIを利用 → UI関連の変更にコストがかからなくなる •GraphQLを利用 → データ関連の変更にコストがかからなくなる SwiftUIとGraphQLのまとめ ユーザーに価値を届けやすくなる
変更に対応しやすくなる
ɹ ɹ SwiftUI + GraphQL
ɹ ɹ •Viewとセットで、必要なデータをQuery(Fragment)で用意する •UIレイアウトと参照データの定義を1対1で宣言しておく(データ取得も宣言的に行う) •SwiftUIのリアクティブなレンダリング機構と、 Apollo-iOSのコード生成+キャッシュ機構を組み合わせて実現 •レイアウト定義とGraphQL定義で実装がほぼ完結する Fragment Colocation(的なこと)
※ STORES ϨδͰಋೖ͍ͯ͠·ͤΜ
ɹ ɹ サンプル画面
ɹ ɹ 必要な実装コードのすべて SwiftUI GraphQL 1ର1
ɹ ɹ 必要な実装コードのすべて データの 参照 Query Mutation SwiftUI GraphQL 1ର1
ɹ ɹ 実装サンプル(取得データの反映) 1. Queryを発行 →内部キャッシュが変更されると自動呼び出し 2. 再レンダリング 3. 状態に応じた表示
ɹ ɹ 実装サンプル(データの更新) 2. キャッシュの更新を検知 (Queryでオーダーノートを参照→それが更新されると呼び出される) 1. Mutationを発行 (オーダーノートを更新) 3.
再レンダリング 4. オーダーノートの更新
ɹ ɹ 実装サンプル データとUIが同期された状態に
ɹ ɹ PreviewでのAPIのモック Previewでのみ、 カスタムのEnvironmentValueをセット
ɹ ɹ Continuous Destruction(継続的な破壊)
ɹ ɹ •SwiftUI •度重なる変更に対して、UIKitでは実現できないスピードで対応を進められた •OSバージョンの変更に対してはまだ弱い •デザインシステムの実装で開発が効率化したが、デザインシステム自体への変更対応は現状最適化できていない •GraphQL •要件や仕様の変更によって、API実装部分が壊れることがほとんどなかった •自動化の仕組みにより、変更に安全に追従していくことができた •開発フローも含めた最適化なども検討していきたい(スキーマファースト開発など)
振り返り と 今後の展望
ɹ ɹ ありがとうございました! SwiftUIと GraphQL最高!