$30 off During Our Annual Pro Sale. View Details »

SwiftUIとGraphQLでプロダクトの継続的な破壊に立ち向かう

たまねぎ
September 19, 2021

 SwiftUIとGraphQLでプロダクトの継続的な破壊に立ち向かう

iOSDC2021 の発表資料です

たまねぎ

September 19, 2021
Tweet

More Decks by たまねぎ

Other Decks in Programming

Transcript

  1. ɹɹ
    ©︎
    hey, Inc
    SwiftUIとGraphQLで新規プロダクトの継続的な破壊に立ち向かう


    ヘイ株式会社 テクノロジー部門 モバイルアプリケーション本部


    STORES レジ iOSエンジニア


    横山 拓也(@_chocoyama)
    iOSDC2021

    View Slide

  2. ɹ
    ɹ
    自己紹介
    横山 拓也 Yokoyama Takuya


    @_chocoyama(Twitter)


    2013.04 ヤフー株式会社入社


    2019.12 ヘイ株式会社入社

    View Slide

  3. ɹ
    ɹ
    CD

    View Slide

  4. ɹ
    ɹ
    CD
    Continuous Delivery?
    Compact Disk?
    Creative Director?
    Career Development?
    Cash Dispenser?

    View Slide

  5. ɹ
    ɹ
    Continuous Destruction(継続的な破壊)
    ※ Ωϟονʔͩͱࢥͬͯ࢖͚ͬͨͩͰɺͲ͜ʹ΋ఆண͍ͯ͠ͳ͍ݴ༿Ͱ͢

    View Slide

  6. ɹ
    ɹ
    アプリケーションの継続的な破壊
    改善・変更


    (破壊)
    フィードバック
    Ұ౓࡞ͬͯऴΘΓͰ͸ͳ͘ɺ
    ৗʹ࡞ͬͨ΋ͷΛյ͠ͳ͕ΒɺΑΓྑ͍΋ͷΛ໨ࢦ͢
    ● UIの変更


    ● APIの変更

    View Slide

  7. ɹ
    ɹ
    STORES レジ
    ● 実店舗で使うPOSシステムを提供するiPadアプリ


    ● 初期実装から変更がなかった画面はほぼ0


    ● 「実装→フィードバック→修正」のサイクルを

    何度も高速に実行


    ● リリースまでに少なくとも3回ほど

    フルリニューアルしている

    View Slide

  8. ɹ
    ɹ
    STORES レジの概要

    View Slide

  9. heyが提供するSTORESプラットフォームの中の新しいプロダクト


    ネットショップと1つになった新しいPOSレジアプリ

    View Slide

  10. ɹ
    ɹ
    主な機能
    ● お会計


    ● 決済手段管理


    ● 精算


    ● 商品・在庫管理


    ● ネットショップ連携
    ϨδΞϓϦ
    ϨγʔτϓϦϯλʔ
    ΩϟογϡυϩΞʔ
    STORES ܾࡁ୺຤
    όʔίʔυϦʔμʔ

    View Slide

  11. ɹ
    ɹ
    技術スタック
    ● フレームワーク:SwiftUI, Combine


    ● APIクライアント:Apollo-iOS(GraphQL)


    ● SDK:STORES 決済SDK

    View Slide

  12. ɹ
    ɹ
    破壊(変更)への対応

    View Slide

  13. ɹ
    ɹ
    変更に対応していく必要性
    変更 Ձ஋
    ࣮૷ ֬ೝ ϦϦʔε
    ユーザーに価値を与え続けるには、変更は避けられない
    ࢼߦࡨޡ
    ܧଓతͳվળ
    ϑΟʔυόοΫ
    ϑΟʔυόοΫ

    View Slide

  14. ɹ
    ɹ
    変更に対応しやすい


    → ユーザーに価値を届けやすい
    変更に対応していく必要性

    View Slide

  15. ɹ
    ɹ
    SwiftUI

    View Slide

  16. ɹ
    ɹ
    SwiftUIの強み
    ● 宣言的シンタックスで

    シンプルな記述ができる


    ● Previewを活用して

    高速にUIの確認ができる

    View Slide

  17. ɹ
    ɹ
    UIKitとの比較
    1.レイアウト変更時の修正


    2.表示の確認

    View Slide

  18. ɹ
    ɹ
    1. レイアウト変更時の修正
    ᶃ DescriptionϥϕϧΛ࡟আ
    ᶄ Ձ֨දࣔͷฒͼͱҐஔมߋ

    View Slide

  19. ɹ
    ɹ
    UIKit + AutoLayout
    1.不要なViewを削除


    2.Viewが消えたことによる不整合を修正


    3.位置変更するViewのAutoLayout貼り直し


    4.Outlet接続関連のコードを削除
    ࡟আ
    Ҡಈ

    View Slide

  20. ɹ
    ɹ
    SwiftUI
    ① 削除
    ② VStackの


    外に移動
    ③ HStackを削除、


    Textの順番を逆に
    Before After

    View Slide

  21. ɹ
    ɹ
    レイアウト変更のしやすさ
    UIKit+AutoLayout SwiftUI
    依存ファイル 多い 少ない
    修正ステップ 複雑 単純
    安全性 クラッシュの恐れ コンパイラで保証
    特有のスキルが必要 素早く安全に対応可能

    View Slide

  22. ɹ
    ɹ
    表示の確認
    •「UIの変更→表示確認」のサイクルの速さは、開発効率に直結する


    •複数の表示パターンがあるUIの場合、特に確認コストがかかる

    View Slide

  23. ɹ
    ɹ
    なんか違う…
    UIKit + AutoLayout
    •表示が実行時と異なる場合がある


    •確認はアプリを起動して対象画面に遷移する


    •1度に1パターンしか確認できない


    •修正と起動のサイクルを繰り返す可能性がある
    このパターン
    はOK
    全部確認


    できた!
    मਖ਼ɾىಈ
    मਖ਼ɾىಈ
    मਖ਼ɾىಈ

    View Slide

  24. ɹ
    ɹ
    SwiftUI + Xcode Preview
    •アプリの起動が必要ない


    •修正内容が即時で確認できる


    •任意の状態を再現したPreviewの実装を残せる


    •実装とPreviewを1対多の状態にできる


    •(コードだけでも表示イメージがしやすい)
    一気に


    全部確認


    できた!
    मਖ਼ɾىಈ

    View Slide

  25. ɹ
    ɹ
    SwiftUI + Xcode Preview

    View Slide

  26. ɹ
    ɹ
    表示確認のしやすさ
    UIKit+AutoLayout SwiftUI
    アプリの起動 必要あり 必要なし
    パターンごとの確認 毎回起動 1度のPreview実行
    継続的な利用 できない できる
    高コスト 低コスト

    View Slide

  27. ɹ
    ɹ
    デザインシステムに則った


    共通UIライブラリを作成
    STORES レジでの変更への取り組み
    •デザインチームが独自のデザインシステムを構築


    •アプリデザインはこれをベースに画面設計
    変更に耐え得る


    仕組みとして

    View Slide

  28. ɹ
    ɹ
    デザインシステム = デザイン原則をまとめたスタイルガイドやその実装などの仕組み


    以下のような価値を生む


    ● 一貫性のあるIFでユーザー体験を向上


    ● デザイナーとエンジニア間の共通言語を確立


    ● 局所最適されたデザインを抑制し、デザイン・開発コストを削減
    デザインシステムとは

    View Slide

  29. ɹ
    ɹ
    共通UIコンポーネントの例
    ※ Preview༻ͷViewΛ࣮ߦ࣌ʹݺͼग़ͯ͠ɺUIΧλϩάͷΑ͏ͳػೳΛ࡞͍ͬͯ·͢

    View Slide

  30. ɹ
    ɹ
    •汎用的に使えるUIを切り出し


    •→ 切り出し単位はデザインシステムに合わせるだけ


    •デザイナーとエンジニアの画面構築工程が揃う


    •→ パーツを組み合わせるだけで画面ができる


    •アプリ内 SwiftPackageManager で対象コンポーネントを管理


    •→ 依存の切り出し


    •→ ビルドやPreview実行の高速化
    共通UIライブラリの作成
    σβΠϯγεςϜʢ໊শඇެ։ʣ
    σβΠϯγεςϜʢ໊শඇެ։ʣ

    View Slide

  31. ɹ
    ɹ
    実装
    σβΠϯ
    γεςϜ໊
    දࣔύλʔϯΛ
    PreviewͰ໢ཏ
    σβΠϯ
    γεςϜ໊
    σβΠϯ
    γεςϜ໊
    σβΠϯ
    γεςϜ໊
    σβΠϯ
    γεςϜ໊
    σβΠϯ
    γεςϜ໊
    ※ σβΠϯγεςϜ໊͸ඇެ։

    View Slide

  32. ɹ
    ɹ
    利用
    σβΠϯ
    γεςϜ
    σβΠϯ
    γεςϜ
    σβΠϯ
    γεςϜ
    → UI作成のコストが激減
    σβΠϯ
    γεςϜ
    σβΠϯ
    γεςϜ
    σβΠϯ
    γεςϜ
    σβΠϯ
    γεςϜ

    View Slide

  33. ɹ
    ɹ
    •レイアウトの変更が容易

    → 壊しては作るといった繰り返しを気軽にできる


    •UIの表示確認を効率的にできる

    → 実装スピードが上がるだけでなく、継続的なメンテナンスにも活用できる
    SwiftUIの変更しやすさ
    UI関連の変更にコストがかからない

    View Slide

  34. ɹ
    ɹ
    GraphQL

    View Slide

  35. ɹ
    ɹ
    GraphQLとは
    •API用のクエリ言語


    •スキーマによってIFの型が厳密に決まっている

    View Slide

  36. ɹ
    ɹ
    REST APIとの比較
    GraphQL REST
    型付け 強い 弱い
    エンドポイント 1つ 複数
    取得リクエスト Query GET
    更新リクエスト Mutation
    POST/PUT/
    PATCH/DELETE

    View Slide

  37. ɹ
    ɹ
    GraphQLの強み
    1.取得するデータをクライアントが決められる


    2.少ないリクエストで複数のリソースにアクセスできる

    View Slide

  38. ɹ
    ɹ
    1. 取得するデータをクライアントが決められる
    ϦΫΤετ Ϩεϙϯε
    Ұ୴શσʔλΛऔಘͯ͠ɺඞཁͳ΋ͷ͚ͩ࢖͏
    → 必要なデータだけ取得する

    View Slide

  39. ɹ
    ɹ
    2. 少ないリクエストで複数のリソースにアクセスできる
    Φʔμʔৄࡉը໘
    アイテム情報
    を追加したい

    View Slide

  40. ɹ
    ɹ
    REST API の場合
    Orders Items
    APIリクエストが増える
    Orders
    itemIds

    View Slide

  41. ɹ
    ɹ
    REST API の場合
    Orders Items
    APIリクエストが増える
    Orders
    itemIds
    追加の通信処理が必要になり、実装が複雑化する
    OrdersAPIͷ݁ՌΛݩʹɺ
    ItemsAPIΛୟ͖௚͢
    OrdersAPIΛୟ͚ͩ͘

    View Slide

  42. ɹ
    ɹ
    GraphQL の場合
    Orders Items
    APIリクエストが増えない
    Orders
    itemIds

    View Slide

  43. ɹ
    ɹ
    GraphQL の場合
    Orders Items
    APIリクエストが増えない
    Orders
    itemIds
    取得したいデータを追加で指定するだけ

    View Slide

  44. ɹ
    ɹ
    GraphQL の場合
    Orders Items
    APIリクエストが増えない
    Orders
    itemIds
    取得できるデータが増えるだけ

    View Slide

  45. ɹ
    ɹ
    GraphQL の場合
    Orders Items
    APIリクエストが増えない
    Orders
    itemIds
    同時に複数のQueryを投げられる

    View Slide

  46. ɹ
    ɹ
    STORES レジでの変更への取り組み
    1.APIに変更が入ったことの自動検知(独自実装)


    2.APIのIFとなるSwiftコードの自動生成(Apollo-iOSの機能を活用)

    View Slide

  47. ɹ
    ɹ
    1. APIに変更が入ったことの自動検知(独自実装)
    Appエンジニア
    想定したデータが取得できません
    BEエンジニア
    ドキュメントの更新漏れてました
    BEエンジニア
    API完成しました
    Appエンジニア
    APIがエラーになります
    BEエンジニア
    変更の共有忘れてました
    人力での変更管理には限界がある
    ケース1 ケース2

    View Slide

  48. ɹ
    ɹ
    1. APIに変更が入ったことの自動検知(独自実装)
    旧スキーマ


    ファイル
    新スキーマ


    ファイル
    App
    BE
    旧スキーマ


    ファイル
    新スキーマ


    ファイル
    ࠩ෼νΣοΫ
    自動でSlackに変更通知


    →共有漏れや不正な定義の参照を防ぐ
    GitHub Bitrise

    View Slide

  49. ɹ
    ɹ
    2. APIのIFとなるSwiftコードの自動生成(Apollo-iOSの機能を利用)
    スキーマ


    ファイル
    BE
    クエリ


    ファイル
    スキーマ


    ファイル
    ੩తղੳ
    Swiftコードを自動生成


    →BEとAppでAPI定義が同期される
    Local
    Apollo
    GitHub

    View Slide

  50. ɹ
    ɹ
    •取得したいデータが増えても「追加リクエスト不要」で「IFの型が自動生成される」

    → 意図した変更に対応しやすい


    •API側の変更をシステム的に追従可能なので、人力のコミュニケーションに頼る必要がない

    →意図していない変更にも対応しやすい
    データ関連の変更にコストがかからない
    GraphQLの変更しやすさ

    View Slide

  51. ɹ
    ɹ
    •SwiftUIを利用 → UI関連の変更にコストがかからなくなる


    •GraphQLを利用 → データ関連の変更にコストがかからなくなる
    SwiftUIとGraphQLのまとめ
    ユーザーに価値を届けやすくなる
    変更に対応しやすくなる

    View Slide

  52. ɹ
    ɹ
    SwiftUI + GraphQL

    View Slide

  53. ɹ
    ɹ
    •Viewとセットで、必要なデータをQuery(Fragment)で用意する


    •UIレイアウトと参照データの定義を1対1で宣言しておく(データ取得も宣言的に行う)


    •SwiftUIのリアクティブなレンダリング機構と、

    Apollo-iOSのコード生成+キャッシュ機構を組み合わせて実現


    •レイアウト定義とGraphQL定義で実装がほぼ完結する
    Fragment Colocation(的なこと)
    ※ STORES ϨδͰ͸ಋೖ͍ͯ͠·ͤΜ

    View Slide

  54. ɹ
    ɹ
    サンプル画面

    View Slide

  55. ɹ
    ɹ
    必要な実装コードのすべて
    SwiftUI GraphQL
    1ର1

    View Slide

  56. ɹ
    ɹ
    必要な実装コードのすべて
    データの


    参照
    Query
    Mutation
    SwiftUI GraphQL
    1ର1

    View Slide

  57. ɹ
    ɹ
    実装サンプル(取得データの反映)
    1. Queryを発行


    →内部キャッシュが変更されると自動呼び出し
    2. 再レンダリング
    3. 状態に応じた表示

    View Slide

  58. ɹ
    ɹ
    実装サンプル(データの更新)
    2. キャッシュの更新を検知


    (Queryでオーダーノートを参照→それが更新されると呼び出される)
    1. Mutationを発行


    (オーダーノートを更新)
    3. 再レンダリング
    4. オーダーノートの更新

    View Slide

  59. ɹ
    ɹ
    実装サンプル
    データとUIが同期された状態に

    View Slide

  60. ɹ
    ɹ
    PreviewでのAPIのモック
    Previewでのみ、


    カスタムのEnvironmentValueをセット

    View Slide

  61. ɹ
    ɹ
    Continuous Destruction(継続的な破壊)

    View Slide

  62. ɹ
    ɹ
    •SwiftUI


    •度重なる変更に対して、UIKitでは実現できないスピードで対応を進められた


    •OSバージョンの変更に対してはまだ弱い


    •デザインシステムの実装で開発が効率化したが、デザインシステム自体への変更対応は現状最適化できていない


    •GraphQL


    •要件や仕様の変更によって、API実装部分が壊れることがほとんどなかった


    •自動化の仕組みにより、変更に安全に追従していくことができた


    •開発フローも含めた最適化なども検討していきたい(スキーマファースト開発など)
    振り返り と 今後の展望

    View Slide

  63. ɹ
    ɹ
    ありがとうございました!
    SwiftUIと
    GraphQL最高!

    View Slide