『ドメイン駆動設計入門』を読んだ
DDD に入門した。
きっかけ
業務でアーキテクチャ(をちゃんと考える必要があるほど複雑なアプリケーションではなかったけど)を考えるときに、DDD の概念を共通言語として知っておいたほうが良さそうだと思ったのがきっかけ。大学生の時に DDD を勉強しようと思ってエリック・エヴァンスのドメイン駆動設計を眺めたけど、内容があまり理解できなかったので、簡単そうな『ドメイン駆動設計入門』から読むことにした。
感想
具体的なコードとそのコードの何が問題か、それをどう解決するのかを提示してくれるのでわかりやすい。DDD に登場する概念と、それがどう役に立つかを知ることができる。エリック・エヴァンスの〜や実践ドメイン駆動設計のような書籍を読む前に一度この書籍に目を通しておけば、それらに書いてあることがさっぱりわからないということにはならなそう。
DDD について少しでも知識があるという人にとっては、この書籍は簡単すぎる気がする。値オブジェクトもエンティティも知りません、程度の人にならちょうど良い気がする(自分がそう)。次は実践ドメイン駆動設計を読んでみたい。
自分の体験をもとに考えたこと
小さいアプリケーションや、やや複雑なスクリプトを作るときは、型と関数だけで済ませることが多かった。これは、ドメインオブジェクトは単なるプリミティブな型の集まりで、振る舞いは全てドメインサービスに任せている、といえるかも知れない。
リポジトリは DDD 関係なく一番役に立つ考え方かも知れない。「本番ではデータを永続化するがテストではインメモリで良い」とか「手元で動かすならファイルに書き込んで、クラウドサービスを使うならそのクラウドで提供されているデータストアを使う」とか、データの保存先を変えたいときは結構あると思う。
で、「詳細の決定はあえて先延ばしにする」ということを知って、当時はそれの実現方法をパッと考えられなかったけど、今は「リポジトリみたいにすればいいよね」と考えられる。
全体的に、変更の影響をできるだけ小さくするにはどうすればいいか、みたいな話をしている気がする。
以下、内容のメモ。
ドメインについて
- ドメイン:プログラムを適用する対象となる領域
- ドメインモデル:ドメインの概念をモデリングして得られたモデル
- ドメインオブジェクト:ドメインモデルをソフトウェアで動作するモジュールとして表現したもの
DDDのパターン
- 知識を表現するパターン
- 値オブジェクト
- エンティティ
- ドメインサービス
- アプリケーションを実現するパターン
- リポジトリ
- アプリケーションサービス
- ファクトリ
- 知識を表現する、より発展的なパターン
- 集約
- 仕様
(1.4 本書で解説するパターンについて p.10)
値オブジェクト
値オブジェクトの性質として以下が挙げられる。
- 不変である
- 交換が可能である
- 等価性によって比較される
値オブジェクトは不変なので、変更したいときはオブジェクトを交換する。値オブジェクトの持つ属性が同じであれば、それらの値オブジェクトは等価である。
値オブジェクトを使って嬉しい点として以下が挙げられる。
- 表現力が増す
- 属性に制限を加えられる
- 型チェックの恩恵を受ける
エンティティ
エンティティの性質として以下が挙げられる。
- 可変である
- 同一性により区別される
値オブジェクトとは違い、エンティティは可変であり同一生(id
)によって区別される。
値オブジェクトとエンティティの違いとして、ライフサイクルを持つかどうかも挙げられる。ここでいうライフサイクルが何を意味するのかはわからないが、明示的に作成〜削除されるのがエンティティだと理解した。
サービス
ソフトウェア開発の文脈で語られるサービスはクライアントのために何かを行うオブジェクトです。 (4.1 サービスが指し示すもの p.66)
基本的にサービスは状態を持たない。
ドメインサービス
ドメインオブジェクトに持たせると不自然な振る舞いを持たせるオブジェクト。ドメインサービスは状態を持たない。
アプリケーションサービス
ユースケースを実現するオブジェクト。詳細の実装は知らないまま、ドメインオブジェクトやドメインサービスを使って目的を達成するサービス、と理解している。
Data Transfer Object (DTO)
ドメインオブジェクトが持つ値だけを持つオブジェクト。
ドメインオブジェクトをそのまま返すとそのドメインオブジェクトを通していろいろな操作ができてしまう。ドメインオブジェクトが持つデータを移し返した DTO を返すことで、データの操作部分を隠すことができる。
ファクトリ
オブジェクトの生成を責務とするオブジェクト。オブジェクトの生成に複雑な処理が必要な場合に用いられる。ファクトリを利用することでコンストラクタ
オブジェクトが持つデータを利用して別のオブジェクトを生成するメソッドは、ファクトリとして機能しているといえる。
集約
(理解が怪しい)
不変条件を維持する単位。
集約のルートとなるオブジェクトだけが関連するオブジェクトを操作する。ルートとなるオブジェクトは関連するオブジェクトの不変条件を維持する。
仕様
評価基準に達しているかを判定するオブジェクト。例えば、is~
という条件を満たすかどうかを真偽値で返すメソッドは仕様オブジェクトに相応しい。