ユーザインターフェース・アプリケーション層・ドメイン層(核)・インフラ層 各層は分離されているべき。ドメインを隔離するメリットは、それ以外のものを取り去って、ドメインの設計に集中できること。
モデルを表現する3パターンの要素
- エンティティ
- 状態が異なったり、別々の実装を跨いだりしたとしても追跡されるような、連続性と一意性を持ったものを表現
- 値オブジェクト
- サービス
関連:モデルにおいて辿ることのできる関連それぞれに対応して、ソフトウェアにおいても同じ特性を持つ仕組みが存在する
-
エンティティ(参照オブジェクト): 同一性(区別すべき)を持つオブジェクト
-
エンティティにとって最も基本的な責務は、振る舞いが明確で予測可能になるように、連続性を確立すること。
-
値オブジェクト:ドメインにおける記述的な側面を表現し、概念的な同一性を持たないオブジェクト。その属性しか関心の対象とならないのであれば値オブジェクト。
-
関連
-
サービス:モデルにおいて独立したインターフェースとして提供される操作。純粋にクライアントに対して何が実行できるかという観点から定義される。
- 優れたサービスの特徴
- 操作がドメインの概念に関係しており、その概念がエンティティや値オブジェクトの自然な一部でない
- ドメインモデルの他の要素の観点からインターフェースが定義されている
- 操作に状態がない
-
モジュール(パッケージ)
リポジトリ
- クライアント側はDBを直接いじるのではなくて、インフラ層を介して触る
- データベースクエリを自由に行うと、実はドメインやデータベースと集約のカプセル化に違反しかねない。インフラやデータベースアクセスを露呈させてしまうと、クライアントが複雑になり、モデル駆動設計が不明瞭になる。
- リポジトリの利点
- クライアントに対して、永続化されたオブジェクトを取得し、そのライフサイクルを管理するためのシンプルなモデルを与える
- アプリケーションとドメインの設計を、永続化技術や複数のデータベース戦略、さらには複数のデータソースからも分離する
- オブジェクトアクセスに関する設計上の決定を下す
- テストで使用するために、ダミーの実装で置き換えるのが容易になる
モデリングパラダイム
パラダイムを混在させるときはモデル駆動開発設計に忠実であれ
オブジェクトにはライフサイクルがあり、誕生した後は様々な状態を経て、最終的には死ぬ。(削除orアーカイブ)
- 集約
関連するオブジェクトの集まり。データを変更するための単位。集約メンバの中で、外部のオブジェクトが参照を保持していいのはルートだけ。
エンティティと値オブジェクトを集約の中にまとめ、各集約の周囲に境界を定義すること。各集約に対してルートとなるエンティティを1つ選び、境界内部に存在するオブジェクトへのアクセスはそのルートを経由して制御する。外部オブジェクトが参照を保持できるのはルートのみとする。内部のメンバに対する一時的な参照を渡して良いのは、単一の操作で使用するときだけ。
- ファクトリ
オブジェクトや集約全体を生成するのが複雑になったり、内部構造をさらけ出しすぎていたりする場合、ファクトリによってカプセル化が実現される。
ファクトリは生成物と非常に緊密に結合するので、ファクトリを所属させるのは、その生成物に対して密接で自然な関係を持つオブジェクトだけにするべき。
何か隠蔽したいものがあるのに、自然な置き場所がないときは専用のファクトリオブジェクトかサービスを定義する。
インターフェースを設計する
- *各操作はアトミックでなければならない。*完全な生成物を生成するのに必要なものは、ファクトリとのやりとり1回で全て渡さなければならない。
- *ファクトリはその引数と結合する.*入力パラメータを慎重に定義しないと、入り組んだ依存関係を作り出しかねない。
ファクトリは生成するオブジェクトや集約に関する不変条件が、全て満たされていることを保証する責務を負う。
格納したオブジェクトを再構成する
- *再構成に使用されるエンティティファクトリでは、新しい追跡IDを割り当てることができない。*識別用の属性は、格納されているオブジェクトを再構成するファクトリに対する入力パラメータの一部でなければならない。
- オブジェクトを再構成するファクトリは、不変条件の違反を違う形で制御する。
- クライアントに対して、永続化されたオブジェクトを取得し、そのライフサイクルを管理するためのシンプルなモデルを与える。
- アプリケーションとドメイン設計を、永続化技術や複数のデータベース戦略や複数のデータソースからも分離する。
- オブジェクトアクセスに関する設計上の決定を伝える。
- テストのためのダミーに置き換えるのが簡単.
リポジトリは基底にあるデータストアをカプセル化する
- 型を抽象化する
- クライアントから切り離す利点を活かすこと
- トランザクション制御をクライアントに委ねること
ファクトリとの関係
ファクトリは、オブジェクトのライフサイクルに置ける始まりを処理し、リポジトリは中期から終わりを管理するのを助ける。ファクトリは新しいオブジェクトを生成し、リポジトリは古いオブジェクトを見つけ出す。
関係データベースに合わせてオブジェクトを設計する
- データベースをオブジェクトの格納先としてみる場合、マッピングツールの能力に関わらず、データモデルとオブジェクトモデルをかけ離れたものにしてはならない。
- オブジェクトシステムの外部にあるプロセスからは、そうしたオブジェクトの格納先にアクセスしてはいけない。
- ドメインを隔離する:アプリケーションの導入
ドメインの責務が他の部分と混ざらないようにレイヤー化アーキテクチャを適用してドメイン層を区切る。
- エンティティと値オブジェクトを区別する
- ドメインの関連を設計する
- 集約の境界
- オブジェクトの生成