Now in Android に学ぶ最新アーキテクチャ:なぜこの構造が必要なのか
🌅 はじめに
Google の公式サンプル Now in Android は、現代の Android 開発におけるベストプラクティスを一通り体現している。
単なる “きれいなコード例” ではなく、
なぜこのようなアーキテクチャが必要なのか(嬉しさ)
使わないとどんな問題に苦しむのか(痛さ)
を理解する教材として特に優れている。
この記事では、Now in Android が採用しているアーキテクチャを、機能単位の構造・依存関係・責務分離の観点から、背景と目的に焦点を当てて整理する。
🏛️ アーキテクチャの全体像
構成レイヤ
-
UI(Feature)レイヤ
-
Domain(ビジネスロジック)レイヤ
-
Data(Repository)レイヤ
-
App(DI / Navigation 管理)レイヤ
これらをモジュールごとに明確に分割し、依存の向きも固定している。
依存方向:
UI → Domain → Data
App は各モジュールを束ねる立場。
🎯 Why:このアーキテクチャの嬉しさ
① UI変更によるバグ波及が激減する(責務が固定化される)
UI は表示とイベント処理だけに集中し、
Domain は “アプリとして何をすべきか”、
Data は “どのデータソースから取得するか”
に専念する。
UI が仕様変更しても Domain/Data が無傷で済むため、改修の影響範囲が小さい。
適用しない場合の痛さ
-
UI から直接 Data を叩く「密結合」が発生
-
ViewModel が巨大化しメンテ不能
-
新 UI(Compose → WearOS → TV)追加時に全崩壊して作り直し
② テスト容易性が圧倒的に高まる(Fake で差し替え可能)
Now in Android は UI previews / FakeRepository を大量に組み込んでおり、
UI のテストでは Data の実装を完全に切り離したまま UI だけ動かせる。
【情報】Repository をインターフェイス化し domain に置くため、簡単に Fake 実装と差し替えできる。
適用しない場合の痛さ
-
Firebase や Room とつながないと UI が動かない
-
ネットワークオフでテストできない
-
Preview で落ちる
-
UI レベルのバグ検証に毎回 API を叩く羽目になる
③ “機能単位のモジュール化” によりスケールしやすい
Now in Android は典型的な「feature module」を採用している。
例:articles、foryou、bookmarks、settings など。
これにより、
-
変更理由が明確
-
コード探索がしやすい
-
ライブラリ単位でビルドが走るためビルド時間短縮
-
役割が肥大化しにくい
Feature 単位の分離は将来の dynamic feature 化も容易。
適用しない場合の痛さ
-
app モジュールが破裂して 5000ファイル超えの沼
-
影響範囲が不明で怖くて触れなくなる
-
リファクタリングの難易度が指数関数的に増加
④ 依存方向が “一方向” に決まり、構造が自然に保たれる
Now in Android の最重要ポイントの1つは、
上位レイヤは下位レイヤに依存してもよいが、逆依存は禁止
というルールを堅持していること。
Domain ← Data の逆依存を防ぐために
Repository のインターフェイスを domain 側に置く。
【成功】これにより、domain がアプリの中心(中核)として整い、長寿命のコードになる。
適用しない場合の痛さ
-
Entity(DB 用構造体)が全レイヤに漏れ出す
-
バックエンド変更に UI 全体が巻き込まれる
-
Clean Architecture の “依存逆転” が破壊される
-
最終的にクリーンアップ不能になる
⑤ DI(Hilt/Koin)とモジュール境界が噛み合う
App モジュールに DI graph を置き、
各 Feature が Repository や UseCase を受け取る。
これにより
-
モジュール間の依存点が明確
-
何がどこで提供されるか可視化
-
テスト用 graph と本番用 graph を切り替えやすい
適用しない場合の痛さ
-
“どこで何を作ってるか” がブラックボックス化
-
画面ごとに new Repository() してしまう
-
ライフサイクル違反でクラッシュしやすい
⑥ UI は常に状態 UiState を優先し、副作用が減る
Compose と ViewModel が UiState を共有し、
イベント(UiAction)を Domain に渡してデータ処理を行う。
Now in Android はこれを徹底しているため、
UI の同期ズレが起こらない。
UI と状態のバインディングが明確で、バグ発生時も原因を特定しやすい。
適用しない場合の痛さ
-
「UI は更新されたが内部状態が変わってない」問題
-
LiveData/StateFlow の多重ハンドリング
-
イベント二重発火
-
ロード中表示揺らぎ(Loading→Success→Loading→…)
🧩 レイヤごとの役割と “嬉しさ”
🎨 UI(Feature)
-
Compose + ViewModel
-
UI 専用の State と Action
-
Repository の存在は知らず UseCase のみ知る
嬉しさ:
UI 仕様変更に強い。テストしやすい。
🔍 Domain(UseCase)
-
アプリのビジネスルール
-
Repository インターフェイス定義
-
複数データソースを統合する責務
嬉しさ:
API 変更や DB 変更を吸収する中心レイヤ。
📦 Data(Repository 実装)
-
RemoteDataSource
-
LocalDataSource
-
RepositoryImpl
嬉しさ:
Room / Retrofit / Firebase を自由に差し替えられる。
⚙️ App(DI / Navigation)
嬉しさ:
画面間依存を整理しやすい。startup の制御が容易。
🚨 アーキテクチャを採用しない場合の総合的な痛み
以下は実案件でよく見るアンチパターン。
-
ViewModel が “神クラス化”
-
Repository がデータモデルを漏らす
-
画面をまたいだ
mutableStateOfの共有地獄 -
DB / API / UI の全修正が連動する
-
新機能追加のたびに既存コードが壊れる
-
チーム内で設計思想が崩壊する
-
バグ修正のコストが雪だるま
Now in Android の構造は、これらを避け “長期メンテナンス性” を最重要視した設計。
🌈 まとめ
Now in Android のアーキテクチャは
Clean Architecture + Modularization + DI + Compose の統合デザイン
であり、ポイントは “見た目がきれい” だからではない。
長期運用で崩壊しない Android アプリを作るための構造
という必然性に基づいている。
得られる嬉しさ(メリット)
-
影響範囲が明確
-
テストが容易
-
UI/Domain/Data の独立性
-
大規模化しても崩れない
-
複数プラットフォームへの展開が容易
適用しない痛み(デメリット)
-
密結合による修正コスト増大
-
UI とデータの同期ズレ
-
テスト不能状態
-
構造の劣化が加速
Now in Android は現時点で最も “実運用寄り” の教科書であり、アプリを長期的に育てたい開発者にとって最良のリファレンスになる。