設計実装のみならず技術浸透のための取り組みも含めて解像度高く紹介されており、どのプレゼンも非常に濃い内容だった。ひとつめのTCAに関するプレゼンは、すでに自社プロダクトにTCAを導入している身としては復習要素もありつつ、Reducerの採用/非採用について感覚的だった部分が言語化されていたため、学びになった。
イベントページ:https://cyberagent.connpass.com/event/342952/
The Composable Architecture (TCA) を用いたAmebaのリアーキテクチャ
@devdazy さん
- 従来:MVVM + RxSwift、VMは状態持たずデータを流すハブだけ
- 課題:ロジックの複雑さ。モデル肥大化、可読性低下、保守性拡張性の低下とともに開発速度が低下
- VM が状態を保持せず SwiftUI と相性悪い、RxSwift 依存が Concurrency と相性悪
- TCA の概要
- メリット・デメリット
- Good:ロジックが明確になり、見通しが良くなる
- すべてのイベントが列挙される。非同期処理のEffectで状態更新できないため、成功失敗を網羅的に書かざるを得ない
- テストの網羅生にもつながる
- e.g. 読み込みだけでなく、読み込み完了後の処理もテスト書かなければ失敗する
- Good:画面遷移をシームレスに移行できる
- SwiftUI → UIViewControllerへの遷移
- TCA x UIKitでは、ほとんど SwiftUI と同じインターフェイスで実現できる
- Good:ロジック分割が簡単にできる
- ロジックである Reducer を別の Reducer に分割・合成したりできる
- Action / State は親からも観測できる
- Bad:学習コストが高い
- フレームワーク丸々ひとつに対する理解が必要
- TCA独自の記法
- 例を作り、マイグレーションドキュメントを作り、テンプレ機能を活用する
- Bad:パフォーマンスが最良ではない
- Reducer を分割しやすい反面、不要な View にも Reducerをつけがち。(Action送る処理は負荷が高い)
- Action を極力減らすよう吟味が必要
- View 側での処理完結も選択肢に
- Bad:Point Freeに依存
- RxSwiftの例に同じ
- 記法のブレがかなり抑制されるのは Good
- Good:ロジックが明確になり、見通しが良くなる
Q&A
- 分割粒度について:画面の量にもよるが、スクロールしない画面では基本的に1画面 1 Reducer だが、セクション持つような単位ではセクションごとに分割する
- ロジック持たない限りは Reducer 持たせない(ボタン置いてあるだけとか)、通信して自身を更新するばあいは Reducer を持たせる
SwiftUI導入から1年、SwiftUI導入とVueFluxライクな状態管理
@TyrionJP さん
- SwiftUI導入の背景
- SwiftUI経験者増の傾向、可読性やメンテナンス性、アンチ Storyboard
- 既存アーキテクチャとの整合性
- VueFlux の単一方向のデータフローを踏襲(
StateObject/ObservableObject)
- VueFlux の単一方向のデータフローを踏襲(
- VueFluxについて(Action / Mutation / State / Computed)
- VueFluxライクな状態管理 (UIKit + VueFluxとの比較)
- メリット:SwiftUI の恩恵、テスタビリティ、ライブラリ依存の少なさ
- デメリット:ボイラープレートと画面数に伴うコード量の増加、Adapter の肥大化
Q&A
- デメリットの方が多そう。既存のエンジニアの移行容易性としての動機があったはずだが、他のアーキテクチャ検討は?
- VueFlux自体ボイラープレート増える傾向あったが、とにかくSwiftUIを使いたい思いがあった
- TCAは検討したがライブラリ依存が発生するため避けた
大規模プロジェクトにおける段階的な技術刷新について
@akkyie さん
- ABEMA:開局10年間の技術的負債
- Kotlin Multiplatform の導入と理想形
- 負債化した依存や設計実装を引き継ぎながらの段階的移行はコスト高
- 別PJ作り、実装を移行していった
- 移行の進め方
- KMP 実装に Xcode PJ を作成追加、依存ライブラリ管理は SPM
- SPM や Concurrency など新規技術スタックを導入
- 既存実装へアクセスできないようにし依存を絶った、逆の既存 → 新規の参照は可能
- 既存からは画面単位で新規実装を利用、ルーティング組み込みやすく
- Feature flag により切り替え、段階的に適用範囲を広げられるようにした(ストラングラーフィグ・パターン)
- 新PJの技術スタック
- SPM、外部依存管理のみでマルチモジュール定義には使っていない(XcodeGen を継続使用)
- KMP との相性問題:KMP 側も都度ビルドしたいが、SPM 側の制約が多い(詳細スライド)
- SwiftUI、状態管理は SwiftUI、ルーティングは UIKit ベース
- Concurrency、Swift 6 モードは有効にしていないが Strict Checking Completed
- Objective-C との相性でランタイムクラッシュ発生
- 運用ポリシーを明文化している(詳細スライド)
- TaskBag 型の導入 (cf. RxSwfit / DisposeBag)
- Concurrency Playground を社内共有しキャッチアップ (Xcode Playground で作成し、class /actor の比較)
- SPM、外部依存管理のみでマルチモジュール定義には使っていない(XcodeGen を継続使用)
Q&A
- SPM マルチモジュールもどして Concurrency Checking 対応大変だったと思うが(ひとつのターゲットにまとまっていると使う or 使わないの移行が大変)
- Xcode PJ で、SPM によるモジュール分割はしていないが、Xcode ターゲットとして分割している
SwiftUI移行のためのインプレッショントラッキング基盤の構築
@pihero13 さん
- 現状:UIKitが支配的(画面は UIKit、セル は SwiftUI)
- 新規:SwiftUI 主体とし、UIKit を逆にスポット利用する(グラデや動画再生プレイヤなど)
- インプレッショントラッキング:
- 行動ログ:ユーザー行動ログ(画面遷移、何を見、何をクリック)
- そのうち、どの要素がユーザーに見られたか
- 実装
onAppearでログ実行するシンプル実装- 「見た」の定義は複雑:要素の 80% が画面内に2秒以上、、など
- SwiftUI で基盤構築
- UIKit ではインプレッショントラッキングの基盤があった
TrackableScrollView+.trackablemodifierImpressionTrackingControllerを@StateObjectで定義しenvironmentに持たせる
- 工夫
- デバッグ画面に参考実装デモを用意した
- シミュレータだけでなく実機やメジャーバージョンでもチェック
- UI Test への活用(画面回転、バックグラウンドの行き来)
- デバッグ機能: Environment Variables を使って、トラッキング対象にオーバーレイ
Q&A
- Trackable view で個々にの計算だとけっこうカクつきそうだが
- 現状リリース画面ではカクつきない、初期実装で
onChangeでGeometryReaderのフレームを個々に監視する検証をしたら、1秒間のアップデート監視が膨大で error が表示された ScrollableView側で監視し、controller経由で view に渡すことで監視view個数を減らすようにシた
- 現状リリース画面ではカクつきない、初期実装で