エリックエバンスのドメイン駆動設計の「第5章 ソフトウェアで表現されたモデル」まとめ

エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計

今回は、「第5章 ソフトウェアで表現されたモデル」のまとめです。

概要

基本要素

モデルと実装を結びつけるための基本要素は、以下の5つとなっています。

  1. 関連

  2. エンティティ

  3. 値オブジェクト

  4. サービス

  5. モジュール

これらの構成要素によって、モデルはソフトウェアという形に具現化されます。

また、実装の際に避けられない妥協を行う場合でも、基本要素を意識することにより、大きく道を外すこともなくなります。

モデルを表現する要素

ドメイン駆動設計において、モデル要素の持つ意味を明確にできるようなパターンが存在します。

概念を何らかのパターンで定義することで、その概念の責務が明確になります。

そのパターンとは、5つの基本要素のエンティティ、値オブジェクト、サービスの3つです。

1.関連

概要

ドメインモデルと実装を結びつけることが重要なので、モデルにおいて辿ることのできる関連は、コードにおいても同じように辿る仕組みが必要です。

ただ、概念間の関連は、モデル上で描くのは簡単かもしれないが、実装となると複雑になることがよくあります。

そのため、関連を扱いやすくする方法があります。

関連を扱いやすくする方法

関連を扱いやすくする方法は、以下の3つの方法があります。

  1. 関連を辿る方向を強制する。

  2. 制約をつけて、多重度を効果的に減らす。

  3. 本質的でない関連を除去する。

関連を辿る方向を強制する
  • 関連を双方向から一方向にすることにより、相互依存関係が減り、設計がシンプルになる。

  • ドメインを理解して、本来はどちらの方向性が重要であるのかを明確にする。

  • それでも双方向が残るなら、双方向であることがドメインの特徴となる。

制約をつけて、多重度を効果的に減らす
  • 制約をつけることによって、1対1の関連にする。

  • 制約により重要なルールが明示的にモデルへ組み込む

僕の現場での経験からすると、制約という考え方をよく使ってます。

1対多の関係になる2つの概念があった場合、1対多だとモデル上もコード上も扱いにくいケースがよくあるので、制約を用いて1対1にしています。

ただ、今はこのような制約を暗黙のルールにしているケースが多いので、これからは明示的なルールとなるようなモデルを作ろうと思いました。

本質的でない関連を除去する
  • ドメインにおける重要度を反映させるように、関連を限定する。

2.エンティティ

定義

  • ある概念が属性ではなくビジネス上の同一性によって識別される場合は、エンティティとして定義する。

例えば、ECサイトでAさんとBさんが同じ商品を購入して注文を受け付けるというケースがあった場合、Aさんの注文とBさんの注文を識別する必要があるかどうかでエンティティか値オブジェクトどうかが決まります。このケースだと識別する必要があるので、エンティティになります。

  • ビジネスのライフサイクルにおいて、エンティティの形態と内容が変化しても、連続性のつながりを維持する必要ある。

先ほどの例だと、注文という概念のビジネスライフサイクルとして、注文受付→発送→着荷→代金回収というイベントが発生していくことになるかと思います。

その際、各イベントが発生したら、エンティティの内容は変化するけど、同じ注文として扱う必要があるということです。

責務

  • エンティティを識別する手段を提供。

  • ライフサイクルにおける各振る舞いを提供。

  • 各ライフサイクルに必要な属性のみ保持。

3.値オブジェクト

定義

  • 属性値のみ関心の対象となる場合は、値オブジェクトとなる。

先ほどのECサイトの例だと、注文された商品名は値オブジェクトに該当します。

責務

  • 保持する属性に関係した振る舞いを提供する。

  • 値オブジェクトの粒度は、値オブジェクトを保持する側の関心ごとに合わせる。

例えば、以下だと「イケテル顧客」は保持する側の関心ごとに合っていますけど、「ダメな顧客」は住所部分が細かいので保持する側の関心ごとに合っていません。 f:id:mmm-mao:20150522075600j:plain

4.サービス

定義

  • 実体・概念よりも活動(クライアントに対して名にが実行できるか)を表現したい場合はサービスとなる。そのため、操作の名前が必ずユビキタス言語の一部にすること。

責務

先ほどのECサイトの例だと、注文を受け付けるというのがサービスとなります。

5.モジュール(パッケージ)

定義

  • ドメインの大きすぎる概念を分割していく。

分割することをモジュール化と呼んでいるが、モジュール化のメリットして、全体から見たらモジュールの詳細を無視して、モジュール間の関係を見ることができる。 また、モジュールの詳細を見たかったら、全体に圧倒されずに、見ることができる。

重要なこと

  • 相互に独立して理解でき、理論づけることのできる概念をモジュール化して、モジュール間を低結合で実現すること。

  • モデルがドメインの概念に従って分割され、対応するコードも同じように分離されるようになるまで、モデルを改良すること。

  • 採用した技術的なフレームワークの規約に沿って、ドメイン層のモジュール化を行うと、概念的な要素がバラバラになるので、モデルとコードが連動しなくなる。あくまでドメインから見た観点で分割すること。

  • モジュール名はユビキタス言語で定義され、ドメインに対する本質を反映する

以上が「第5章 ソフトウェアで表現されたモデル」のまとめです。