はじめに
本記事は以下の書籍を読んで学んだことをまとめることを目的としています。
前回の続きです。
ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本 | 成瀬 允宣 |本 | 通販 | Amazon
DDDで出てくる概念
DDDで出てくる概念を整理します。
エンティティ
エンティティの性質は以下です。
- 可変
- 同じ属性でも区別
- 同一性による区別
前回値オブジェクトの説明で
stringでは表せない文字数制限や入力できる文字種の制限など、そのシステム固有のルールを表現をしたい、かつ値の性質を適用したいときに使われます。値の性質とは以下が挙げられます。
- 不変
- 交換可能
- 等価性による比較
と説明しました。エンティティは値オブジェクトを逆の性質も持つといえます。
エンティティの性質が少しわかりにくいと思ったので、値オブジェクトとの違いを意識してもう少し説明します。
- 可変
- 値オブジェクトと異なり、Changeメソッドなどで属性を変更させることができます。代入による変更はしなません。
- 同じ属性でも区別
- 値オブジェクトは等価性による比較が行われ、同じ属性であれば区別されませんでしたが、エンティティは同じ属性でも区別されます。例えばNameプロパティを持つオブジェクトがあったとして、同じ値が入ったインスタンスがあったときに、値オブジェクトであれば、同じものとみなされますが、エンティティの場合は別物になります。
- 同一性による区別
- 同じ属性で見分けがつかないと困るので、エンティティ同士を区別するために識別子による比較をします。インスタンスの属性を変更したとしても識別子という同一性によって、変更前と同じものであると認識されます。
値オブジェクトとエンティティのどちらを使えばよいか
何を値オブジェクトにして、何をエンティティにするかは非常に難しいと思います。
その一つの解決策として、ライフサイクルが紹介されていました。
例えば「ユーザー」というオブジェクトの場合、アプリケーションの会員登録で作成されたり、退会して削除されたり、とライフサイクルが存在するため、エンティティになります。
「名前」というオブジェクトの場合、ユーザーの属性として値の性質を持つオブジェクトとして利用されることが考えられます。アプリケーションの中でライフサイクルとして表現することは無意味であるため、値オブジェクトになります。
可変なのか不変なのかで判断できそうです。
ただし、同じ概念を持っていたとしても、システムによって値オブジェクトとなるのか、エンティティとなるのかは変わります。そのため、構築したいシステムによってしっかり考える必要があると思いました。
ドメインオブジェクトのメリット
値オブジェクト、エンティティという二つのドメインオブジェクトについて学びました。
なぜこのような概念が必要かというと、前回と同じような話になるのですが、オブジェクトの意味や仕様がコードを読むだけでわかるドキュメント性を高めるため、仕様の変更を局所化しロジックの散在を防ぐためです。
上記のメリットから、なるべくドメインオブジェクト自身が自分のことを色々語るように、自分のことは自分でやるように設計するのが良いと私は理解しています。
ドメインサービス
値オブジェクトやエンティティといったドメインオブジェクトに記述するには不自然な振る舞いはドメインサービスに記述します。
不自然な振る舞いとは、複数のドメインオブジェクトに跨って処理されるようなときに多く見られるそうです。
確かに、自分自身のことを自分でやることは普通のことですが、ほかのオブジェクトを全て確認するなど、そのドメインオブジェクトが本当にやるべき責務なのかは一度考えた方がよさそうに思いました。
実装上の注意
- ドメインオブジェクトと異なり、ドメインサービスには自身の振る舞いを変更するような状態をもたない
- むやみにドメインサービスに振る舞いを書かない。ドメインオブジェクトに書くべき振る舞いが、サービスに漏れて、自分自身で何もしなくなってしまうと、ドメインモデル貧血症となる
- 迷ったらドメインオブジェクトに振る舞いを書くべき
ドメインモデル貧血症がなぜいけないのか?
ドメインオブジェクトのメリットである「オブジェクトの意味や仕様がコードを読むだけでわかるドキュメント性を高めるため、仕様の変更を局所化しロジックの散在を防ぐため」がなくなってしまうからです。
自分自身で何もできないオブジェクトを見ても、どんなルールがあるかわからないし、ルールを守るためのロジックも散在してしまいます。
さいごに
ここまでお読みいただき、ありがとうございました。
長くなるので、#3に続きます。