この章では、本書で扱ってきた考え方を、 実在する小さな Android アプリに当てはめてみます。
題材は「口座振替メモアプリ」です。
- 電気料金
- クレジットカード
- サブスクリプション
といった 引き落とし元 と 引き落とし先 を記録し、 「どこから、何が、どう引き落とされているのか」を把握するためのアプリです。
DDD の用語を説明する章ではありません。 どう判断し、どこに線を引いたか を追う章です。
要件整理と言葉の定義
最初にやったのは、クラス設計ではありません。 言葉を揃えること でした。
このアプリでは、次のような言葉が登場します。
- 口座
- 引き落とし
- 引き落とし元
- 引き落とし先
- メモ
ここで重要なのは、「それぞれが何を指すのか」を明確にすることです。
たとえば、
- 「口座」は銀行口座だけを指すのか
- クレジットカードは口座なのか
- 引き落とし元と引き落とし先は対等な存在か
この時点で、次のように定義しました。
- 引き落とし元
- 実際にお金が減る側(銀行口座やクレジットカード)
- 引き落とし先
- 電気料金やサブスクなど、支払いの理由となるもの
- 口座振替
- 「引き落とし元」と「引き落とし先」を結びつける関係
この定義は、コードより先に決まっています。 そして、この言葉がそのままクラス名や変数名になります。
境界の決定
このアプリで最初に決めた境界は、たった一つです。
「UI は、引き落としの判断をしない」
- 有効かどうか
- 表示すべきかどうか
- どちらが元で、どちらが先か
こういった判断は、UI に書かないと決めました。
その結果、
- UI は「表示するだけ」
- 判断は ViewModel より下に集まる
という自然な流れが生まれます。
この時点では、
- Domain 層という名前のパッケージ
- UseCase クラス
は、まだ存在していません。
境界だけを先に決める ことで、 構造は後から追いついてきます。
データ → ドメイン → UI の流れ
実装が進むにつれて、次の流れが安定してきました。
- Data
- 永続化や取得の責務
- Domain
- 「これは何か」「どう扱うか」の判断
- UI
- 表示とイベント通知
重要なのは、この流れを 最初から意識して作っていない ことです。
- Repository から取得したデータを
- ViewModel でそのまま使うのが苦しくなり
- 「ここで判断したい」という塊が見え
- そこに名前をつけた
結果として、
- 「口座振替」という概念
- 「引き落とし元」「引き落とし先」という役割
が、ドメインとして浮かび上がりました。
DDD 的に言えば「ドメインモデルが見えた」状態ですが、 実際には 困りごとに名前をつけただけ です。
実装スケッチ
ここでは、雰囲気が伝わる程度のスケッチだけを示します。
Repository は、データの取得に専念します。
- 条件付きの SQL
- フィルタリング
- 並び替え
こういった処理は持ちますが、 「それが何を意味するか」は知りません。
次に、判断が集まり始めた場所に、小さなクラスを置きます。
- 引き落とし元かどうかを判定する
- 表示用の名前を決める
- UI が迷わなくて済む形に整える
この時点で、初めて「これはドメインだ」と呼べるものになります。
UI 側は、
- 状態を受け取る
- 表示する
- ユーザー操作を通知する
だけになります。
コード量は減っていません。 しかし、迷う場所は確実に減ります。
実例から分かること
このアプリでは、
- 最初から DDD をやろうとしなかった
- 境界を 1 箇所だけ決めた
- 言葉を揃えた
- 困ってから名前をつけた
という順序で設計が進みました。
結果として、
- 仕様追加に耐えやすい
- UI がシンプル
- 判断の置き場所に迷いにくい
構造になっています。
この章のまとめ
実例を通して伝えたかったのは、次の一点です。
DDD は「設計手法」ではなく、「どの判断を先に固定し、どの判断を後で変えるかを意識する姿勢」だということ
- どこで判断するのか
- なぜそこに置いたのか
- 後で壊せるか
これらを説明できるなら、それは十分に DDD です。
クラス構成や層の名前は、後からいくらでも変えられる。 しかし、「どこで判断するか」という境界だけは、早い段階で決めておく必要があります。
大きな理論も、立派な用語も必要ありません。 自分たちのアプリにとって、意味のある境界を引けているか それだけが重要です。