Upgrade to Pro — share decks privately, control downloads, hide ads and more …

日経iOSプロジェクトのマルチモジュール戦略

Go Takagi
September 13, 2023

 日経iOSプロジェクトのマルチモジュール戦略

Go Takagi

September 13, 2023
Tweet

More Decks by Go Takagi

Other Decks in Technology

Transcript

  1. ⽇経 iOS プロジェクトの 
 マルチモジュール戦略 Go Takagi  2 02 3

    / 09 / 13 After iOSDC LT Night 〜 ピクシブ×⽇経×タイミー 〜
  2. Me ( Go Takagi ) ‣ID • shimastripe / shimastriper

    • bento.me/shimastripe ‣Work at • 株式会社 ⽇本経済新聞社 ‣ iOS エンジニア ‣ iOSDC NOC チーム ‣Like • Swift / ⾃動化 / 柴⽝ 2 電⼦版広報⽝デンシバ iOSDC 2 023 UIContentCon fi guration!!
  3. SPM MultiModule 5 Application Monolith App Feature Feature Feature Usecase

    Common Usecase Common Repository Common ........... ........... ........... Swift Package Manager の各パッケージ App
  4. KPIツリーと施策効果から⾒るアプリの役割 9 ݱ৔ͷࢪࡦͷࣄۀߩݙΛ໌֬ʹ ࣄۀՁ஋ (LTV) ܧଓ݄਺ F V ๚໰ස౓ ফඅهࣄຊ਺

    ղ໿཈ࢭ Net ARPPU ηοτ঎඼୯Ձ ηοτ঎඼ߪೖ਺ ൢചख਺ྉ ೔ܦIDܾࡁൺ཰ ిࢠ൛ϓϥϯൺ཰ ՝ۚऀ਺ MAU ৽نདྷ๚ऀ ࠶དྷ๚ऀ ແྉτϥΠΞϧਃ ࠐ ॳճ՝ۚ཰ ՝ۚ཰ ిࢠ൛ͷࣄۀՁ஋ΛߴΊΔͨΊʹ͸ɺ՝ۚऀ਺Λ૿΍͢ɺ ՝ۚ୯ՁΛ্͛Δɺܧଓ݄਺Λ૿΍͢͜ͱ͕ඞཁ
  5. 成⻑し増加する画⾯‧Extension間のコード共有 ‣ マクロ分岐 • #ifdef IS_APP 等があちこちに...... ‣ TargetMembership •

    依存関係の把握が必要‧ビルド時間も伸びる ‣ WatchApp との兼ね合い • UserDefaults や Keychain が繋がっていない ‣ ⾮同期処理‧DataBindingの管理 • App は RxSwift、AppExtension は Combine でそれぞれ重複実装していた • Concurrencyに移⾏したい........ 1 0
  6. 改善したい、抱えている痛み ‣ 古いモジュールの改善‧それに伴う⼗分なドキュメントの整備 • メンテしづらい‧AppExtension の制約等の考慮 • テストを書きつつ現代ではいらないコードを消したい ‣ 依存⽅向をきちんと管理

    • 無視した変更が⼊れづらい設計を保証する仕組みにしたい ‣ ⾮同期処理周り • RxSwift‧Combine のコードを Concurrency に移⾏したい ‣ ビルド時間の改善 • 画⾯数が多いため、ビルド時間が⻑くて開発効率に響いている 1 2
  7. AppExtension をまず整理 ‣ App の Subset であるため取り組みやすかった • Core になる仕組みを整理していく

    • 前処理Macroの整理‧共有している最⼩限のロジック群を把握 ‣ WatchOSの考慮 • Keychain‧UserDefaults など永続化周りを抽象化してAppの場合と住み分ける ‣ Combine ベースの⾮同期処理を Concurrency に置き換える • API‧DB などの Data 層の処理まで⼀旦 Concurrency 移⾏ • ⼀定サイズを移⾏後、Usecase や UI 層にも⼿を付け移⾏していく • App も RxSwift 向けに変換して利⽤する形で部分的に移⾏‧徐々に割合を増やしていく 1 4
  8. Package.swift でレイヤー依存関係を定義 1 5 // MARK: - Utility // ֤ϨΠϠʔͷύοέʔδΛ༻ҙ͢Δศརؔ਺

    protocol TargetProtocol { var category: String { get } var name: String { get } var hasTest: Bool { get } var testDependencies: [TargetDependency] { get } var allDeps: [TargetDependency] { get } /// default extension var dependency: TargetDependency { get } var targets: [Target] { get } }
  9. レイヤー間の依存関係を制御 1 6 extension Data { static let orgUserRepository: Self

    = .init( name: "OrgUser", layer: .repository, dataDeps: [.keychainKit], domainDeps: [.model, .repositoryProtocol], hasTest: true ) }
  10. MultiModule に移しつつコードを刷新する ‣ global な Extension の整理 • MultiModule に移して思わぬビルドエラーを踏んで把握

    ‣ ⾮同期処理 • Concurrency で書き直して、RxSwift を持ち込まない • Combine は場合によって許容 ‣ DI • pointfree/swift-dependencies を採⽤して @Environment ベースで DI ‣ テスト • スコープを絞って整理が進むのできちんと書いていく 1 7
  11. 開発環境はどう変化してきたか 2 0 Project CLI ツール パッケージマネージャー CI XcodeGen +

    
 MultiModule + Swift Playgrounds Mint SwiftPM + Renovate Bitrise (Fastlane) (今)
  12. MultiModule + Swift Playgrounds へ移⾏中 2 2 Application Monolith App

    Feature Feature Feature Usecase Common Usecase Common Repository Common ........... ........... ........... Swift Package Manager の各パッケージ App
  13. MultiModule + Swift Playgrounds へ移⾏中 2 3 Application Feature Feature

    Feature Usecase Common Usecase Common Repository Common ........... ........... ........... 保存記事App More... 紙⾯選択画⾯App 該当箇所のみビルドしてミニアプリ⽣成
  14. Swift Playgrounds ミニアプリ ‣ アプリを画⾯単位で確認したい • 通常分割は⼤変 • エントリーポイントを変える仕組みもない •

    設定ファイルもたくさん必要 ‣ Swift Playgrounds をミニハック • iPad (+ Mac) で Swift だけでアプリを作れる • 簡単なアプリしか作れない...? • マルチモジュールを Import してミニアプリを作れる • Package.swift の書き換えは想定されていない⽅法なことだけ注意 2 4 https://www.apple.com/jp/swift/playgrounds/ Demo.swiftpm ├── Package.swift └── Sources/MyApp/MyApp.swift エントリーポイントを容易に追加できて嬉しい
  15. Xcode Preview との使い分けは悩み中 ‣ Preview 安定しない問題 • 特定のライブラリに依存して失敗するようになりやすい • 回避できるけど問題は"気づいたら"壊れているのが⾟い

    ‣ 現状のミニアプリの利点 • 安定してビルドして確認できる • 設定をユースケースに応じて動的に変えたりリッチなPreviewが作れて嬉しい • ミニアプリで有効な機能はApp側のDebug機能に移すことも 2 5
  16. Stricted Concurrency Checking ‣ MultiModuleでもまだ ON にはしてない • 古いコードからの移⾏がつらくなるため •

    度々⼿元でオンにしてみて様⼦⾒ • 特に UI レイヤーで ON にすると⼀気に⼤変な量のエラーに 😇 2 6
  17. TestPlanを⾃動整備 ‣ TestTarget‧TestModule がどんどん増えていく • 内部の JSON はシンプル • 以下のコマンドでモジュールの⼀覧は取れる

    • xcrun --sdk macosx swift package --package-path MultiModule describe --type json • ビルド時に jq で TestPlan の⾃動アップデート 2 7 { "containerPath": "container:MultiModule", "identifier": "UseCase", "name": "UseCase" }
  18. Xcode Template を整備 ‣ 標準ベースで書き直したモジュールに Template を⽤意 • APIRequest‧DB •

    swift-dependencies 周りの Template • ただ基本シンプルなものしか作れない • より複雑なTemplateが必要になったら Sourcery を検討する予定 2 8 https://github.com/krzysztofzablocki/Sourcery
  19. DoCCを整備 (したい) ‣ いくつか問題点を抱えてまだ導⼊できず • plugin が platform: Mac 専⽤

    • Xcode の generate docs でも • 特定のライブラリの docc ファイルを⾒てエラー....... • 複数 Scheme をまとめるドキュメント⽣成ができない 2 9 https://github.com/apple/swift-docc-plugin/issues/ 38 DoCC の運⽤ Tips ぜひ知りたいです!
  20. まとめ ‣ Project の状態は様々 • MultiModuleへの移⾏は⼀般に時間がかかる • 痛みを認識し、そこから取り組んでいったほうが効果が実感できて良い • アプリが⼤きくなるとより継続性が⼤事

    ‣ ⽇経のマルチモジュール移⾏→標準ベースのリアーキテクチャも兼ねる • OSの機能をリッチに活かしながらモダンな技術を利⽤できる環境 • OSの機能はアプリチームが⼀番詳しいので積極的に起案して作ってます • まだまだ⼀部だけで移⾏中。興味を持った⽅、弊社にぜひ声かけてください! 3 0