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

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

Avatar for Go Takagi Go Takagi
September 13, 2023

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

Avatar for Go Takagi

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