- Jetpack Compose が設計を強制するもの
- UI State は「ドメインの投影」である
- 非同期状態をドメインに持ち込まない
- StateHolder / Reducer パターンの現実的な使い方
- ViewModel は「状態の翻訳者」
- 状態を持ちすぎないという選択
- この章のまとめ
Jetpack Compose が設計を強制するもの
Jetpack Compose の登場によって、Android の設計は大きく変わりました。特に影響が大きいのが、「状態を中心に UI を組み立てる」という考え方です。
Compose では、
- UI は状態の結果として描画される
- 状態が変われば UI が再描画される
- 状態を正しく持てないと UI が破綻する
という前提が、半ば強制されます。
これは単なる UI フレームワークの違いではなく、設計の中心が状態管理に移った ことを意味します。
UI State は「ドメインの投影」である
UI State は、しばしば「画面表示のためのデータ」として扱われます。しかし、本書では UI State を次のように捉えます。
UI State は、ドメイン上の判断結果を UI 用に投影したもの
つまり、UI State 自体が判断を持つべきではありません。
- 表示してよいかどうか
- 操作を許可するかどうか
- 次にどの状態へ遷移するか
これらはドメイン側で決まり、その結果が UI State として表現されます。この関係を意識すると、状態管理の責務が明確になります。
非同期状態をドメインに持ち込まない
Loading / Error / Success といった非同期状態を、ドメインモデルに含めてしまう設計を見かけることがあります。しかし、これはドメインの関心事を曖昧にします。
非同期状態は、
- 通信や I/O の都合
- UI 表示のための必要情報
であり、ドメインそのもののルールではありません。
ドメインは「成功した結果」や「失敗の意味」を扱い、Loading かどうかは UI 側で管理する方が、責務が分離されます。
StateHolder / Reducer パターンの現実的な使い方
状態管理の手法として、StateHolder や Reducer パターンが紹介されることがあります。しかし、これらを厳密に適用しようとすると、コード量が一気に増えがちです。
本書では、次のような使い方を推奨します。
- 状態遷移が複雑な画面に限定して使う
- すべての画面に強制しない
- Reducer は「状態遷移のルール」を閉じ込める場所として使う
あくまで 必要なところにだけ導入する道具 として扱うことで、設計と実装のバランスを保てます。
Reducer パターンの具体的な実装例は、別紙「参考:Reducer を使う場合・使わない場合のサンプル」を参考にしてください。
ViewModel は「状態の翻訳者」
Compose 時代の ViewModel は、単なるデータ保持クラスではありません。本書では、ViewModel を次のように位置づけます。
ドメインの判断を UI State に翻訳する存在
- Domain → UI State への変換
- 非同期処理の調停 (ドメイン側に非同期処理を実装しない)
- UI からのイベントをドメインに渡す
ViewModel がこの役割に集中できていれば、UI は状態を表示することに専念できます。
状態を持ちすぎないという選択
Compose では、すべてを State として持ちたくなりがちです。しかし、状態が増えすぎると、逆に全体像が見えなくなります。
- 一時的な UI 状態は remember で閉じる
- 画面をまたがない状態は ViewModel に上げない
- 永続化が必要なものだけを状態として持つ
「どこに状態を持つか」は、設計判断そのものです。State を減らすことも、立派な設計です。
この章のまとめ
Jetpack Compose 時代の Android 設計では、
- 状態管理が設計の中心になる
- UI State はドメイン判断の結果である
- 非同期や表示都合をドメインに混ぜない
という整理が重要になります。
次章では、Repository の責務を Android 文脈で再定義し、どこまでを Repository に任せるべきかを見ていきます。