Page	1/120
2016/12/18
Java女子部	イベント
ゆるふわ														
DDD入門!
Page	2/120
自己紹介
名前
 robo	(	兼高理恵	)
お仕事
 Java	技術者
 要件定義に設計から実装まで
好きなもの
 モバイル端末
Page	3/120
はじめに
ゆるふわ	DDD入門!	におこしいただいて
ありがとうございます。
私見ですが…
ドメイン駆動設計は、	オブジェクト指向プログラミングを理解し、
開発経験が豊富なエンジニアが、	書籍エリック・エバンスのドメイン駆動設計と
実践ドメイン駆動設計を読み解き、	現場で実践しないと身に付かないようです。	
今回は、私の力不足から、
ゆるふわなドメイン駆動設計の入門者よりの話になっています。
Page	4/120
	
DDDに興味を持たれたり、深堀したい方は、
「ぐぐれば」既にお歴々の方々が解説してくださっていますので、
そちらの資料を確認してくだいね。
併せて、	エリック・エバンスのドメイン駆動設計や	実践ドメイン駆動設計や
オブジェクト指向プログラミング関連の書籍を読み進められると良いと思います。	
ドメイン駆動設計を本格的にシステム設計に取り入れたい
…と思っていたみなさま、ごめんなさい。
Page	5/120
参考図書
Page	6/120
エリック・エバンスのドメイン駆動設計
エリック・エバンスのドメイン駆動設計
ソフトウェアの核心にある複雑さに立ち向かう
エリック・エバンスさんの視点でドメイン駆動設計を解説したバイブル本です。
著者はベテランエンジニアであり、その知識と経験を前提に話が進むので、
読み進むためには前提知識を学ぶ努力が必要です。
Page	7/120
「日本語版への序文」より
日本語版への序文(エリック・エヴァンス	Eric	Evans)
根本的には、DDDを駆動している原則は次の3つだけです。
コアドメインに集中すること。
ドメインの実践者とソフトウェアの実践者による創造的な共同作業を通
じて、モデルを探求すること。
明示的な境界付けられたコンテキストの内部で、ユビキタス言語を語る
こと。
Page	8/120
「日本語版への序文」より
この原則はきわめて完結です。
しかしもちろん、これで十分ではありません。
まず、この原則はいくつかの用語の定義に依存しています。
そして、この定義は本書の最も重要な内容の一部なのです。
また、これらの原則を名確に理解してたとしても、成し遂げるのは容易では
ありません。
偉大なソフトウェアを作り上げるためには、知性と忍耐が必要です。
同様に勇気が必要であり、リスクもある程度は受け入れなければならない
のです。
Page	9/120
「序文	(Martin	Fowler)」より
序文	(マーチン・ファウラー	Martin	Fowler)
ドメインモデルというものが、最初にモデル化され、その後で実装されるよ
うなものではない、ということだ。
「まず設計し、その後に構築する」という段階を区切った考え方に対しては、
多くの人々と同様に私も拒絶するようになってきている。
だが、Ericの経験から導き出される教訓は、真に強力なドメインモデルは時
間と共に進化するということであり、偉大なベテランモデラであっても、最高
のアイデアを得られるのはシステムが初期リリースされた後のことだ、とい
うことである。
Page	10/120
実践ドメイン駆動設計
実践ドメイン駆動設計
サンプル	VaughnVernon/IDDD_Samples
ドメイン駆動設計を身につけようとしている人たちへの具体的な指針本です。
エリック・エバンスのドメイン駆動設計を読んでいたほうがよいと思います、	ドメイ
ンイベント、巨大な泥団子の概念、レイヤ化アーキテクチュアからヘキサゴナルア
ーキテクチャへの発展	…などの新たな知見も追加されています。
Page	11/120
プリンシプル	オブ	プログラミング
プリンシプル	オブ	プログラミング
良いコードを書くための「Principles/原則」の紹介と解説をまとめた本です。
「単一責務の原則」や「凝集度」などエリック・エバンスのドメイン駆動設計や実践
ドメイン駆動設計でも利用している概念や用語も含んでいます。	実装経験をもつ
人を対象としているため、具体的なコード説明がなく抽象的な解説になっている
ことに留意ください。
Page	12/120
参考サイト/スライド
DDD難民に捧げる	Domain-Driven	Designのエッセンス
https://www.ogis-ri.co.jp/otc/hiroba/technical/DDDEssence/index.html
ざっくり	DDD	入門!!
http://www.slideshare.net/digitalsoul0124/ddd-17678116
リッチなドメインモデル	名前探し	の旅
http://www.slideshare.net/masuda220/ddd-forname
ドメインオブジェクトの見つけ方・作り方・育て方
http://www.slideshare.net/masuda220/ss-62386442
「実践ドメイン駆動設計」社内読書会まとめ
〜IDDD本難民に捧げる1章から7章〜
http://www.slideshare.net/AtsuoAoki/iddd17
Page	13/120
参考	PDF
Domain	Driven	Design(ドメイン駆動設計)	Quickly	日本語版
https://www.infoq.com/jp/minibooks/domain-driven-design-quickly	
ダウンロードするには、infoQ	へのユーザ登録(メールアドレスとPWの登録)が必要です。
Page	14/120
DDD入門!
Page	15/120
DDD難民に捧げる	Domain-Driven	Designのエッセンス
第1回 ドメイン駆動設計とは
Page	16/120
ドメインモデルとは
ドメインモデルとは
ある業務に特化した、業務的に正確な意味合の取扱データや振る舞いを一般化
して保持するもの。	図や文書および、Javaオブジェクト実装で表現される、DDDを
実践する上で欠かせないもの。
DDDにおけるドメインモデルは、依存関係が絡んだ複雑なモデルをシンプルにし
て扱いやすくするために、	OOPの単一責任の原則に従い、各業務概念をより中
核的な独立した概念に細かく分離(モデリング)していきます。
ですので、たいていコアドメインと複数のサブドメインから成ります。
ドメインモデルは、抽象概念です。
このため単純に利用すると、コアとなる一部分を指すか、事業ドメイン全体をカバ
ーするのか判然としないことに注意してください。
Page	17/120
手続型設計の限界	(モデリングしないと…)
モデリングを使わない(あるいは不十分でも)、
機能を満たすコードによる手続型設計のアプローチでも、
ドメインの機能は実装できます。	
ですが複雑さが爆発していくので、	やがてだれも実態を理
解できなくなりメンテナンスも不能になるでしょう。
Page	18/120
オブジェクト指向で、モデリングする。
オブジェクト指向のアプローチを使えば、
対象概念の振るまいとデータ構造(と状態)が外に漏れ出さないよう隠蔽化してく
れます。	隠蔽化とカブセル化で責務を分離すれば、互いの影響範囲が小さくな
り、全体も見通し易くなります。	新任者であってもメンテナンスし易くなるのです。
一方、機能を満たすコードのみの手続き型の実装は、振るまいと状態がどこから
でも操作できるので、	全ての操作の整合性を管理しない限り、対象概念の振るま
いと状態の一貫性が保証できません。
対象概念を表す重要な業務ロジックでさえ、どこにでも実装できるために、どこに
あるのか、どこまで探せばよいのかすら判りづらくなってしまいます。
Page	19/120
ドメイン駆動設計の視点
DDDの中心となる原則は、議論や傾聴、理解、発見、そして事業価値だそうです。
事業価値を生み出すためには、設計(開発)対象を深く知らなければなりません。
例えば銀行システムなら、事業価値は、銀行業務領域(ドメイン)が元ですから、
ドメインの反映としてのソフトウエアを作成することが最優先となります。
そのためには、ドメインの核となる概念や要素を取り入れて、
関係を正確に再現できるよう、ドメインをモデル化しなければなりません。
ドメインをモデル化できるようにするには、専門家や設計者/開発者が、
お互いにドメイン知識を共有し磨き上げられなければなりません。
銀行システムには、ドメインだけでなくDBなどのミドルウェアも必要です。
ドメインを中心にするには、それらが影響しないよう設計しなければなりません。
…忍耐強くこれらを繰り返します、技術至上主義の考え方ではありません。
Page	20/120
	DDD入門!視点の	ドメイン駆動設計	概略
前ページをドメイン駆動設計のパターン用語で表現しました。
事業価値を生み出すため、業務ドメイン(ドメインモデル)を反映したソフトウェア
の設計/開発を最優先する。
業務ドメイン知識の共有と育成のために、業務の専門家と設計者/開発者でユ
ビキタス言語を育てあう。
ドメインをモデリングして各々の中核の責務により(コア/支援サブ/汎用サブ)ドメ
インに分離していくことで、境界づけられたコンテキストを見つける。
境界付けられたコンテキストどうしは世界が異なるので、ユビキタス言語も異な
っている。
分離した(コア/支援サブ/汎用サブ)ドメインの間でオブジェクトを操作するには
ユビキタス言語の変換が必要なので、変換対応のコンテキストマップを作る。
Page	21/120
	DDD入門!視点の	ドメイン駆動設計	概略
アプリケーションは業務ロジック(ドメイン)だけではなりたたない。	ユーザインタ
ーフェース、アプリケーション、ドメイン、インフラストラクチャのレイヤから成り立
っている。
ドメインと別レイヤとの橋渡しでの責務の流出/流入を防ぐため(ポートとアダプ
ター/ヘキサゴナル)アーキテクチャやドメインイベントを使う。
ドメイン内の状態や値を持つ概念をモデル化するため、同一性の有無からエン
ティティと値オブジェクトを作り、それらのライフサイクルと構造体関係をあらわ
す集約を作る。
ドメイン内の集約の永続化と問い合わせ専用のリポジトリを設ける。
集約や複雑なオブジェクトの生成を委譲するファクトリを導入する。
ドメイン内の中核の責務から外れるロジックの配置場所としてサービスを設け
る。
Page	22/120
	DDD入門!視点の	ドメイン駆動設計	概略
事前に完璧な設計をすることはできない。	ドメインエキスパートが気づかず、設
計者や開発者とのユビキタス言語育成の中で発見される知見もある。	ドメイン
のモデリングやリファクタリングも日々行なわなくてはならない。	より良いソフト
ウェアは、忍耐強くこれらを繰り返して作る。
ドメインモデルは、エンティティや値オブジェクトやサービス…で形作られる
概念なので、XXXドメインモデルというようなクラスはない。
Page	23/120
DDDパターン用語+詳細+α
Page	24/120
単一責務の原則
(SRP:the	Single	Responsibility	Principle)
クラスやモジュールは、ただ1つの原因(要因)により変更されなければならないこ
とを表します。
複数の異る役割の状態や振る舞いを持つような神クラスは、責任(役割)が分割
されていないことを表し、理解が困難かつバグを招くことは経験済みでしょう。
責務(変更の原因となるもの)を探すことは、コードの抽象化に役立ちます。
オブジェクト指向設計の概念として、最も重要なものの1つです。
Page	25/120
凝集性
(Cohesion)
クラスやモジュールの機能の純粋性を表します。
クラス内のメソッドとインスタンス変数においては相互依存性のこと。
機能が全てのメソッドと全てのインスタンス変数を使う場合に最大となります。
インスタンス変数やメソッドの総数自体は少ないことを前提にすると、	一般的に、
凝集性が高ければメソッドとインスタンス変数が無駄なく相互に依存し合っている
ことなので、	全体として1つのロジックになるように設計されている(特定の目的に
特化している)といえます。
Page	26/120
依存関係逆転の原則
上位のモジュールは、下位のモジュールに依存してはならない。
どちらのモジュールも、抽象に依存すべきである。
抽象は、実装の詳細に依存すべきではない。
実装の詳細が、抽象に依存すべきである。
実践ドメイン駆動設計	第4章	アーキテクチュア	より
…という原則。
上位レベルのコンポーネントが、下位レベルへの要求のインターフェース(抽象)を
提供し、	下位レベルは、それを実装することで、上位レベルは、下位レベルの実装
を知らなくても	インターフェース(抽象)を知っていれば使えるようになる。	こうする
ことで実装と抽象の依存関係を逆転させている。
Page	27/120
デメテルの法則
オブジェクトを使用する場合、
直接知っているオブジェクトしか使うべきではないという法則
オブジェクトのメソッド内から実行できるメソッドは、次のいずれかのみ。
そのオブジェクト自身のメソッド
自身にパラメータとして渡されたオブジェクトのメソッド
メソッド引数のオブジェクトから取得した別オブジェクトは使わないこと。
自身の内部でインスタンス化されたオブジェクトのメソッド
自身が保持しており、直接アクセスできるオブジェクトのメソッド
Page	28/120
「命じろ、たずねるな」
オブジェクトを使う場合は、
オブジェクトにクエリをかけて得た情報からコマンドをなげるのでなく、
公開されたインターフェースで定義されたコマンドのみ使うようにすること。
やることが決まっているなら問い合わせによる不必要な負荷を減らすこと。
Page	29/120
ドメインエキスパート
事業価値の元となるドメインの「細部」「ルール」「落とし
穴」「潜在的な問題点」を知っている専門家のこと。
銀行システムを設計/開発するのなら、いちばん銀行業業務(ドメイン)を知ってい
る、	銀行の中で働く人々やその専門家が「ドメインエキスパート」です。
Page	30/120
ユビキタス言語
ユビキタス言語(模範的説明)とは、
適切なドメインモデルを作りあげられるよう、	ドメインの業務知識の共有と各ドメ
インモデルの中核概念を抽出できるようにするために作り上げる、	ドメインエキス
パートやソフトウェア設計者/開発者を含めたチーム全体で意思疎通を可能にし
て、
概念名や操作名だけでなく用法も含めて育て上げる、中核とするドメインの業務
知識用の共有言語(共有用語を含む)のこと。
ユビキタス言語は、特定ドメインを扱うチーム内で育て上げるため、業界全体や
他チームでは意味をなさない。
ユビキタス言語は、境界づけられたコンテキストごとに育て上げるので、境界づ
けられたコンテキストごとに異なる。
よってユビキタス言語で定義した用語は、別の境界づけられたコンテキストで
は、同じ文言でも別の意味になる。
Page	31/120
ユビキタス言語のアンチパターン
組織全体で流通させるユビキタス言語を目指すな
組織全体の意思疎通ができたら良いと、	あらゆる名称が唯一の意味しかもたな
いようにしようとしてはならない。
全ての業務概念についてステークスホルダー全員が納得するような	共通の意味
付けをすることは事実上不可能だからである。
ユビキタス言語は、合意が取れる単位で育成し流通させること。
Page	32/120
ドメインモデル
事業価値の元となるドメインの概念を抽象化(モデル化)し
たもの。
ドメインモデルとは、
Eric	Evansによれば、特定の図で表されるものではなく、伝えようとする概念だそ
うです。
対象のドメインをユビキタス言語に従って表現したものであり、	これがなければ、
何をモデルに取り込み、何を捨てるのかが曖昧になり、	ソフトウェアの全体的な展
望の設計ができません。	したがってソフトウェアの詳細部であるコードの設計も始
められません。
ドメインは、モデリングしていくと中核的な独立した概念に細かく分離されていく
ので、たいていコアドメインと複数のサブドメインに分かれます。
Page	33/120
ドメインモデル貧血症
ドメインモデル貧血症とは、
あるドメイン固有の責務(取扱データや振る舞い)が、	他のドメインに漏れだしてい
るため、ドメインモデルが機能不全になっていること。
上記の問題によりドメインがうまく働かない(不調である)ことを、貧血症になぞらえ
た表現です。
ドメインモデルに、DBなどの外部都合の実装が入り込んでしまっていることも含ま
れます。
Page	34/120
ドメインモデルとユビキタス言語
ドメインモデルのコンポーネントの属性(プロパティ)の名称や、
振る舞い(メソッド)の名称と引数や返値は、ユビキタス言語に従って定義します。
ドメインモデルのコンポーネント(パターン)、
エンティティ、	値オブジェクト、	サービス、	リポジトリ、	ファクトリ、	ドメインイベント…
など。
Page	35/120
コア/支援サブ/汎用サブドメイン
サブドメインや境界づけられたコンテキストを含む、抽象的な業務ドメイン
コアドメイン(境界づけられたコンテキスト)
業務に不可欠で、ドメインの中核となるモデル
支援サブドメイン(A)(境界づけられたコンテキスト)
業務に不可欠だが、コアドメインとは言えないモデル
支援サブドメイン(B)(境界コン+外部の境界コン)
業務に不可欠だが、コアドメインとは言えないモデル
汎用サブドメイン	(境界づけられたコンテキスト)
業務に不可欠でないが、プロジェクト全体で不可欠なモデル
Page	36/120
コアドメイン
業務に不可欠で、ドメインの中核となるモデル
コアドメイン(模範的説明)とは、
コアドメインとは、重要な事業価値があり、見返りが一番大きな最優先投資領域
(ドメイン)のこと。	プロジェクトの目的である事業の中核となるモデルである。
Page	37/120
汎用サブドメイン
業務に不可欠でないが、プロジェクト全体で不可欠なモデ
ル
汎用サブドメイン(模範的説明)とは、
プロジェクト(ソリューション)全体として必要であるが、対象のドメイン内では特に
何もしていない領域のこと。
Page	38/120
支援サブドメイン
業務に不可欠だが、コアドメインとは言えないモデル
支援サブドメインとは、
その内容が特別なもので、業務に不可欠な領域を表しているが、まだコアドメイン
とは言えないようなモデルのこと。
Page	39/120
境界づけられたコンテキスト
境界づけられたコンテキスト(模範的説明)とは、
ドメインモデルを適用する際の概念的な境界(適用範囲⇒コンテキスト)のこと。
ドメイン内のモデルがどこに属すのか(コアドメイン/支援サブドメイン/汎用サブドメ
イン)を表す。
Page	40/120
	境界づけられたコンテキストとユビキタス言語
ユビキタス言語は、
ドメインモデルをつくり上げるために、	ドメインエキスパートや開発者の間で、ある
ドメイン(業務知識)中の各概念をチーム内で共有できるよう、
特定の考え方や判明した知見の切り口で言語化していく(育て上げる)ものです。
このためユビキタス言語中には、
いくつかの「切り口として働く(既存の/創造の)抽象概念」が発生します。
ドメインモデル内では、	この「切り口として働く抽象概念」を共有しているモデル
のグループと	そうでないモデル達との間に(共有物がないので直接取り扱えない
という)境界が発生します。
この「切り口として働く抽象概念」が「境界づけられたコンテキスト」です。
共有物がないので「境界づけられたコンテキスト」ごとに、ユビキタス言語も異る
ことになります。
Page	41/120
	境界づけられたコンテキストとコア/サブドメイン
「境界づけられたコンテキスト」(「切り口として働く抽象概念」)により、	ドメインの
モデルが、コアドメイン、支援サブドメイン、汎用サブドメインのいずれになるかが
決まります。
ドメインの中核となる「境界づけられたコンテキスト」を持っているモデルがコアド
メインです。
ドメインの中核となる「境界づけられたコンテキスト」を持っていなかったモデル
は、	サブドメイン(支援サブドメイン/汎用サブドメイン)になります。
サブドメインは、ドメインとは異るとなるがプロジェクト全体で必要になる	「境界づ
けられたコンテキスト」を持っているか否かで、汎用サブドメインか支援サブドメイ
ンになります。
Page	42/120
	境界づけられたコンテキストとコンテキストマップ
「境界づけられたコンテキスト」が異る(「切り口として働く抽象概念」を共有して
いない)モデルとモデルの間のやりとりには、	お互いのユビキタス言語のすり合
わせのための変換対応が必要になります。
この異る「境界づけられたコンテキスト」間での	ユビキタス言語の変換対応関係
(概略やコード)についてのドキュメントが「コンテキストマップ」です。
Page	43/120
コンテキストマップ
コンテキストマップ(模範的説明)とは、
プロジェクトに関わる境界づけられたコンテキストと、
それらがどのように統合(変換対応)されているのかを示すドキュメントのこと。
Page	44/120
コンテキストマップの重要性
抽象化したドメインのコンテキストマップ
コンテキストマップは、
プロジェクト全体を構成する複数の境界づけられたコンテキスト間の関係を
上流/下流で表し、コンテキストの統合(変換対応)を明確にします。
通常、境界づけられたコンテキストごとに、担当チームも分かれています。
上流/下流の違いとコミュニケーションが必要なチームが判明するので、
作業の担当範囲などのチーム間の合意形成を円滑にします。
Page	45/120
コンテキストマップとチーム間の合意形成
コンテキストマップには、
境界づけられたコンテキストの関係を上流/下流で表わして、作業分担の合意形
成(対応)を求めていました。
上流/下流になるのは、共同作業チームだけでなく、	上層部やレガシーシステムな
ど交渉不能である可能性もあるので、	下記の対応戦略のパターンが挙げられて
います。
共有カーネル、	顧客/供給者の開発、	順応者、	腐敗防止層、	公開ホストサービ
ス、	公表された言語、	別々の道、	巨大な泥団子。
Page	46/120
共有カーネル
共有カーネル(模範的説明)とは、
コンテキスト間での共有に合わせて、チーム間での役割が合意できる場合の戦
略。
コンテキストを共有するチーム間で、コミュニケーション(ユビキタス言語作成)を図
り、	相互でモデルおよび関連物(コードやDBなど)を共有します。
両チームは、共有モデル⇔自分たちのモデルへのマッピング変換を行います。
Page	47/120
顧客/供給者の開発
顧客/供給者の開発(模範的説明)とは、
コンテキスト間の上流/下流に合わせて、チーム間での役割が合意できる場合の
戦略。
上流チームは、下流チームとのコミュニケーション(ユビキタス言語作成)を図り、
下流チームのニーズを考慮して開発を行います。
下流チームは、上流モデル⇒下流モデルへのマッピング変換を行います。
Page	48/120
順応者
順応者(模範的説明)とは、
コンテキスト間の上流/下流に合わせて、チーム間での役割が合意できない場合
の戦略。
下流チームは、上流チームに隷属するメリットを優先し、自分たちのドメインモデル
作成を諦め、	上流チームのユビキタス言語に合わせたモデルを開発します。
上流モデル⇒下流モデルへのマッピング変換は発生しません。
Page	49/120
腐敗防止層
腐敗防止層(模範的説明)とは、
コンテキスト間の共有/上流/下流に合わせて、チーム間での役割が合意できない
場合の戦略。	あるいはユビキタス言語が共有できないレガシーシステムと接合す
る場合の戦略
該当するチームは、両者の間でのモデルの変換を行う隔離レイヤを作成して、	自
分たちのモデルを開発します。
該当チームは、隔離レイヤのモデル⇔自分たちのモデルへのマッピング変換を行
います。
Page	50/120
公開ホストサービス
公開ホストサービス(模範的説明)とは、
(サブシステムの利用など)コンテキスト間を1対多で共有する場合の戦略。
共有サービスを設けることで、車輪の再発明抑止やメンテナンス性を向上させる
戦略
集中先(サブシステム)にアクセスするプロトコルを定義し、	各チーム個別のマッピ
ング変換を担当する共有サービスを公開します。
各チームは、共有サービスを介して共通プロトコル⇔自分たちのモデルのマッピ
ング変換を行います。
Page	51/120
公表された言語
公表された言語(模範的説明)とは、
一般化されているユビキタス言語を使うことで、車輪の再発明を抑止する戦略
コンテキスト間の共有/上流/下流に即した、一般化されたユビキタス言語がある
場合の戦略。
該当するチームは、コミュニティなどで一般公開されているユビキタス言語	(およ
びモデルやライブラリ)を間に挟んで、自分たちのモデルを開発します。
該当チームは、一般公開モデル⇔自分たちのモデルへのマッピング変換を行い
ます。
Page	52/120
別々の道
別々の道(模範的説明)とは、
コンテキスト間での共有が不可欠でなく、チーム間での役割が合意できない場合
の戦略。
コンテキスト間での共有が不可欠でない場合、	該当チームは、両者が一切つな
がりを持たないように設計し、	その狭いスコープ内でのモデルを開発します。
マッピング変換は発生しません。
Page	53/120
巨大な泥団子
巨大な泥団子とは、
コンテキストマップの作成が不能なことを表す概念です。
打つ手がありません。
コンテキスト間での共有/上流/下流どころか、	境界づけられたコンテキストへのモ
デリング(分離/再設計)すら困難な、	様々なモデルが混在し、境界も辻褄があわな
くなっていているもの全体を表す概念	あるいは、そのような問題のある現行業務
や既存システムの例え。
Page	54/120
巨大な泥団子と境界づけられたコンテキスト
ドメインモデルの新規作成であっても、
ドメインの中核概念に基づいたモデリング(分離/再設計)をおろそかにして、
境界づけられたコンテキストの調査より先に様々なモデルを作り続けないでくだ
さい。
そのような状況を放置していると、	中核概念に分割していないことが、当然化、常
識化してしまい、	境界づけられたコンテキストに気づく機会も失ってしまいます。
そして、巨大な泥団子になってしまいます。
Page	55/120
コンテキストマップの統合(変換対応)例
抽象化したドメインのコンテキストマップの統合(変換対応)例
コンテキストマップの統合では、複数の戦略を組み合わせることもできます。
ACL	腐敗防止層(Anti	Corruption	Layer)
OHS	公開ホストサービス	(Open	Host	Service)
PL	公表された言語	(Published	Language)
Page	56/120
アーキテクチャの役割
開発するソフトウェアは、
現実のドメインではなく、ドメインを扱うアプリケーションです。
このため、業務知識のロジック(ドメイン層)だけでなく、
プログラム全体の取り扱いを行うもの(アプリケーション層)や、
ユーザーとの対話を行うもの(ユーザインターフェース層)や、
DBなどのミドルウェアのAPI(インフラストラクチャ層)のレイヤが必要になります。
これらの責務は異るため、
お互いにドメイン貧血症に陥らないようにするアーキテクチャが必要なのです。
Page	57/120
(アンチパターン)利口なUI
UIモデルは、ユーザインターフェース層に属しますが、
UIモデルからドメインを操作するなどのビジネスロジックが入り込んでしまい、
ドメインモデル貧血症を起こしているもの。
Page	58/120
レイヤ化アーキテクチャ
レイヤ化アーキテクチャ(模範的説明)とは、
ドメインを扱うアプリケーションを上位から、	ユーザインターフェース層、	アプリケ
ーション層、	ドメイン層、	インフラストラクチャ層に分けるアーキテクチャ。
ドメインが中心になっておらず従属する形となるので、
近年はポートとアダプターアーキテクチャに置き換えられています。
Page	59/120
ポートとアダプターアーキテクチャ
ポートとアダプターアーキテクチャ	(ヘキサゴナルアーキテクチャ)
ポートとアダプターアーキテクチャは、
対称性を生み出すためのアーキテクチャスタイル。
中心核と	内部(中心核を含む)と	外部(外周)の3つの領域に分ける設計手法。
中心核にドメインモデル、内部にアプリケーション(ユースケース境界/ポート層)、
外部にアダプター(個別クライアントとの接点)を配し、	各アダプターは、対象とす
る特定のクライアント(ユーザインターフェースorインフラストラクチャー)との入出
力を受けもつ。
Page	60/120
ポートとアダプターアーキテクチャ
ポートとアダプターアーキテクチャ	(ヘキサゴナルアーキテクチャ)
アダプター⇒個別クライアント(外向き)へはクライアント側の個別APIを使うが、
個別クライアント⇒アダプター(内向き)へはアプリケーション側の共通APIを使用
する。
アダプター⇒アプリケーション側へは共通インターフェースを介すが、
アプリケーション側のインスタンスはアダプターごとに異なる。
ヘキサゴナルアーキテクチャを使うときには、ユースケースを念頭に置いてアプリ
ケーションを設計すること。
Page	61/120
ポートとアダプターアーキテクチャの例
抽象化したポートとアダプターアーキテクチャの例
個々の外部のクライアントに合わせたアダプターが存在します。
外部から内部へのアクセスには、アプリケーションのAPIを使います。
クライアントは、ユーザインターフェースやインフラストラクチャにあたります。
Page	62/120
(参考)ポートとアダプターアーキテクチャ資料
ドメインモデル中心のアーキテクチャ
https://devtab.jp/entry/internal/42
ヘキサゴナルアーキテクチャ	(Hexagonal	architecture翻訳)
http://blog.tai2.net/hexagonal_architexture.html
Page	63/120
コマンドクエリ責務分離	(CQRS)
コマンドクエリ責務分離	(CQRS)とは、
あらゆるメソッドは、何らかのアクションを実行する「コマンド」あるいは呼び
出し元に	データを戻す「クエリ」のいずれか一方でなければならず、その両
方の機能を兼ね備えてはいけない。
つまり、何かの質問をすることで、その質問への応えが変わってしまっては
いけない。
もうち少しきちんと言うと、メソッドが値を戻すのは、そのメソッドが参照透
過性を持ち、	何も副作用をおよぼさない場合だけでなければいけない。
実践ドメイン駆動設計	第4章アーキテクチュアより
…という原則です。
Page	64/120
コマンドクエリ責務分離	(CQRS)
オブジェクトのレベルから見ると	CQRS	は、以下のような意味になります。
実践ドメイン駆動設計	第4章アーキテクチュアより
あるメソッドがオブジェクトの状態を変更するのなら、そのメソッドは「コマ
ンド」であり、値を戻してはいけない。
メソッドの戻り値は、Javaなら	void	になる。
あるメソッドが何らかの値を戻すのなら、そのメソッドは「クエリ」であり、
直接・関節を問わず、	オブジェクトの状態を変更してはいけない。
このメソッドの戻り値の型をきちんと指定して宣言する必要がある。
Page	65/120
コマンドクエリ責務分離	(CQRS)
ここでのコマンドクエリ責務分離	(CQRS)とは、
サーバの機能を「コマンド」(副作用あり)と「クエリ」(副作用なし)に分ける考え
方です。
例えば集約は、通常だとコマンドとクエリを両方持っていますし、	その集約のリポ
ジトリにもコマンドとクエリのメソッドが存在しますが少々非効率でもあります。
CQRSを使って、クエリの処理を最適化するために、	集約のコマンドとクエリをコ
マンドモデルとクエリモデルに分離します。
コマンド発行によるコマンド状態変更時に、コマンドモデルがコマンド・リポジトリ
への保管と、	クエリモデルの更新ならびにクエリ・リポジトリへの保管を行わせま
す。
コマンド発行の処理が増えてしまいましたが。	クエリ発行では、クエリ・リポジトリ
からクエリモデルを取得するだけでことが済むようになります。
Page	66/120
コマンドクエリ責務分離(CQRS)の例
抽象化したコマンドクエリ責務分離(CQRS)の例
QuPrc:クエリプロセッサ
CmPrc:コマンドプロセッサ(アプリケーションサービス)
EvSBS:(全ての)イベントのサブスクライバ
CmM:コマンドモデル
QumSta:クエリモデルの保存場所
CmMSta:コマンドモデルの保存場所
Page	67/120
コマンドクエリ責務分離(CQRS)の例
ユーザからの入力:
クライアント{ユーザ入力からコマンド発行}
⇒コマンドプロセッサ{コマンド受信からコマンド更新}
		⇒コマンドモデル{状態更新のためコマンド集約を生成}
				⇒コマンドモデル・リポジトリ{コマンド集約を保管}
		⇒コマンドモデル{状態更新のドメインイベント発行}
				⇒イベントサブスクライバ{状態更新のドメインイベント受信からクエリ更新}
						⇒クエリモデル{最新状態反映のためクエリ集約生成}
								⇒クエリモデル・リポジトリ{クエリ集約を保管}
クエリモデルは、ここでは表示していません。
Page	68/120
コマンドクエリ責務分離(CQRS)の例
ユーザからの出力要求:
クライアント{ユーザ出力要求からクエリ発行}
		⇒クエリプロセッサ{クエリ受信からクエリ集約を要求}
				⇒クエリモデル・リポジトリ{クエリ集約を返却}
						⇒クエリプロセッサ{取得したクエリ集約から出力データ生成}
								⇒クライアント{画面出力}
クエリモデルは、出力用の非正規化データです。
Page	69/120
コマンドクエリ責務分離(CQRS)の例
イベントのサブスクライバによるクエリモデルの更新
コマンドモデルは、
クエリモデルが同期するようドメインイベントを発行する必要があります。
コマンドモデルは、状態変更時に状態更新のドメインイベントを発行します。
ドメインイベントを受信するサブスクライバは、
受け取ったドメインイベントに従ってクエリモデルを更新します。
このようにして、
クエリモデルに、コマンドによる最新状態が反映されるようにします。
Page	70/120
イベント駆動アーキテクチャ	(EDA)
イベント駆動アーキテクチャ	(EDA)は、
イベントの作成や検出、消費そしてイベントへの反応を促すアーキテクチャです。
実践ドメイン駆動設計では、
オブジェクトとオブジェクト操作元との結合を切り離す設計手法として利用してい
ます。
クライアントなどの
オブジェクト操作元は、操作するイベントタイプのイベントを発行し、
ドメインオブジェクトは、サブスクライバから購読したイベントタイプを介した間接
的な操作を行うことで、操作元との結合を切り離します。
こうすることでドメインオブジェクトの依存は、メッセージングシステムと購読するイ
ベントタイプのみとなります。
Page	71/120
イベント駆動アーキテクチャの例
抽象化したイベント駆動アーキテクチャの例
イベント駆動アーキテクチャにより、
3つのシステム(ポートとアダプターアーキテクチャ)の結合が切り離なされ、
メッセージングシステム自身と購読するメッセージのイベントタイプだけに依存す
るようになっています。
Page	72/120
イベントソーシング
イベントソーシングは、
オブジェクトへの変更追跡ができるようにするパターンです。
実装ドメイン駆動設計の例でのイベントソーシングでは、
ドメインモデル内の集約のインスタンスへの全ての操作コマンドに対し、
操作コマンドの実行ごとにドメインイベントを発行して、	イベントストアに発生順に
記録させています。
これにより、任意時点での集約の状態が再現(追跡)できるようになります。
任意時点までのイベント(操作コマンド)を発生順に適用させて再現します
Page	73/120
	ドメインモデルと同一性を持つオブジェクト
ドメイン駆動設計のドメインモデルには、現実のドメインの反映が求められます。
ですが社員情報など、同一性をもったオブジェクトは、ドメインロジックで対応でき
ません。	オブジェクトには、ライフサイクルがあり、生成から破棄までを繰り返しま
すが、	ロジックだけでは再生成時の最新状態への反映ができないからです。
同一性をもったオブジェクトには、以下の対応が必要です。
状態が更新された時には、破棄されるまでに、状態をどこかに保管すること。
再生成された時には、保管していた状態を読みだして再現すること。
ひとつの概念を表す集団に含まれる場合は、集団を単位として対応すること。
ドメイン駆動設計では、これらに対応するため、
エンティティ、値オブジェクト、集約、リポジトリのパターンが用意されています。
Page	74/120
エンティティ
エンティティ(模範的説明)とは、
同一性をもつオブジェクトを扱う設計パターン
ドメイン内で特定の、変化していくが同一性を持ち唯一な物を表します。
同一性の保証が必要なオブジェクトです。
一意な識別子と属性や振る舞いを持っていて、	状態が変化しても同一物であるこ
とが識別でき、同じ状態のものがあっても他と区別できます。
同一性をもっている(唯一物である)ため、同型の別インスタンスと交換すること
は無意味です。
Page	75/120
エンティティの設計
エンティティの設計は、
子エンティティのコンテナではなく、値のコンテナとして組み立てること。
エンティティ設計の初期段階では、
エンティティを一意に特定するポイントとなる属性や振る舞いにだけ注目する。
エンティティには、同期対応が必要。
エンティティは、変化できます。
このため変更があれば全ての参照先に伝えて、同期してもらう必要があります。
この問題には、イベント駆動アーキテクチャとドメインイベントの組み合わせで対
応できます。
Page	76/120
エンティティ	(補足)
UUID生成器
Java標準APIには、かなりの確率で完全に一意な識別子を作成する	Universally
Unique	Identifier	(UUID)	UUID生成器が用意されている。
String	rawId	=	java.util.UUID.randomUUID().toString();
擬似乱数生成器と暗号化
SecureRandom	randomGenerator	=	new	SecureRandom();
int	randomNumer	=	randomGenerator.nextInt();
String	randomDigits	=	new	Integer(randomNumber).toString();
MessageDigest	encryptor	=	MessageDigeet.getInstance("SHA-1");
byte[]	rawIdBytes	=	encryptor.digest(randomDigits.getBytes());
Page	77/120
エンティティ属性のバリデーション
属性/プロパティへの操作は、	自己カプセル化(アクセッサメソッド仲介)で行ない、
不適切な値の設定がされないようにします。
自己カプセル化とは、クラス内のデータへのアクセスは、たとえ同一クラス
の中からでも、アクセッサメソッド経由で行うよう設計することだ。
Marfin	Fowler
メリットとして、インスタンス変数を抽象化でき、	他のオブジェクトの属性やプロパ
ティを容易に使えるようになり、	バリデーションあるいはアサーションでの事前チェ
ックもできるようになります。	…が、実践ドメイン駆動設計の著者はこう思ってます。
バリデーションは、単体で個別の関心事であり、バリデーション専任のクラ
スが受け持つ責務である。	ドメインオブジェクトに実装するものではない。
Page	78/120
オブジェクト統合失調症
オブジェクト統合失調症とは、
処理を移譲されたオブジェクトが、委譲元のエンティティ・オブジェクトの識別子を
知らない状況を表します。
エンティティは、同じ状態であっても他と区別できますが、	識別子が判らないた
め、処理を委譲されたオブジェクトは、	委譲元のエンティティを区別できなくなるこ
とをパラノイアになぞらえた表現です。
Page	79/120
値オブジェクト
値オブジェクト(模範的説明)とは、
ドメイン内で特定の、計算や定量化や交換可能な性質の概念を表します。
同一性の保証が必要ない効率化のためのオブジェクトです。
変更不可能(不変)な値の属性と副作用のない振る舞い(関数)を持ち、	値の透過
性から同じ状態のものは区別できず同じものとして扱います。	交換可能性がある
ため、同型の新インスタンスとの交換で状態更新とすることもできます。
振る舞いは副作用を持たず、新しい値を返すことはできますが、自分自身の状
態を変更することはできません。
補足)色コード(#ffffff)を	String	型でなく、ColorCode	型の値オブジェクトにする
と、	単なる文字列でなく、ドメイン内での色コードという概念を表せるようになり
ます。
Page	80/120
値オブジェクトのモデリング
ディスカッションで、
以下のような特徴の概念があれば、値オブジェクトとして定義します。
そのドメイン内の何かを計測したり定量化したり、あるいは説明したりする。
状態を不変に保つことができる。
関連する属性を不可欠な単位として組み合わせることで、
概念的な統一体を形成する。
計測値や説明が変わったときには、全体を完全に置き換えられる。
値が等しいかどうかを、他と比較できる。
協力関係にあるその他の概念に、副作用のない振る舞い(関数)を提供する。
Page	81/120
値オブジェクト:概念的な統一体
概念的な統一体は、	関係する全ての属性の値がないと成り立たないもの。
例)トッピングしたアイスの代金	(アイスとトッピングは全種同額)
代金は、トッピングの個数が決まらないと決定しない。
値オブジェクトはひとつ以上の属性を持っています。
それらがお互いに関連していて、全体をもってこの値の説明ができ、
それらのいずれかを切り離しても、この値の説明ができなくなる。
これらの条件をみたす値オブジェクトは、概念的な統一体です。
Page	82/120
値オブジェクト:状態更新も扱える
エンティティでなくても、値オブジェクトで状態更新を扱えます。
設計中のオブジェクトが状態を更新するので「これはエンティティ!」と
単純に考えないでください。
オブジェクトが同一性をもたないのでしたら、値オブジェクトを使うことを検討して
ください。	値オブジェクトは交換可能性があるので、新インスタンスに置換すること
で状態更新が扱えます。
Page	83/120
値オブジェクト:副作用のない振る舞い
値オブジェトは、エンティティを変更しないでください。
変更するとテストが難しくなってしまいます。
自分自身の状態変更でないからといって、	パラメータとして渡されたエンティティ
の変更はしないでください。
Page	84/120
値オブジェクト:できるだけ値で受け取る
メソッドのパラメータは、
できるだけ値でもらい、値オブジェクトをそのまま受け取らない。
値オブジェクトをそのまま受け取ることは、他人の内部構造を知っている
(依存する)ことになります。
メソッドのパラメータは、実際に使う属性のみを受け取るようにすること。
メソッドのパラメータは、できるだけエンティティを受け取らないようにすること。
  	エンティティの状態変更がないことを保証しにくいため。
//	修正前
float	priority	=	businessPriority.priorityOf(product);
//	修正後
float	priority	=
								businesssPriority.priority(
																product.businessPriorityTotals());
Page	85/120
値オブジェクト:ミニマリズムを考慮
メソッドのパラメータには、
実施に使う値オブジェクトや属性を渡すようにすること。
下流のモデル内の管理負担が最小限になるようにします。
Page	86/120
値オブジェクト:標準型を利用する
値オブジェクトが複数派生する場合は、
標準型を追加して区別できるようにする。
標準型とは、あるものの種類を説明する型のこと。
例えば	ユビキタス言語に	PhonNumber(電話番号)が定義されていているなら、
標準型のPhoneType	を定義すれば、
電話番号がさらに家電話(Home)か携帯電話(Mobile)かを説明できます。
//	電話種別の標準型を定義
enum	PhonType	{Home,Mobile,Other};
Page	87/120
値オブジェクト:永続化判断
永続化するからといって、
必ずエンティティが必要になるわけではありません。
あるオブジェクトを永続化する場合は、	そのオブジェクト型専用のテーブルに格納
されることもあります。	そのテーブルには、主キーも含まれる…だからといって、	オ
ブジェクトがエンティティであると決めつけないでください。
DDDは、ドメインモデルを中心に設計するパターンです。
永続化するオブジェクトが、エンティティか、値オブジェクトで良いのかは、
ドメインモデルが決めることです。
そのためのチェック項目も提案されています。
Page	88/120
値オブジェクト:永続化判断
チェック項目
1.	 今モデリングしているのは、そのドメインにおける何かのものなのだろうか?	そ
れとも、測定値や量など、物の性質についての説明なのだろうか?
2.	 正しくモデリングしてドメインの要素を表したときに、このモデルの概念は、	さき
ほどまとめた値の特徴をすべて(あるいは、ほぼ)満たしているだろうか?
3.	 エンティティを使おうとしている理由は、ベースにあるデータモデルが、	ドメイン
オブジェクトをエンティティとして扱うことを求めているからというだけのことなの
だろうか?
4.	 エンティティを使おうとしている理由は、ドメインモデルが一意な識別子を必要
としていて	個別のインスタンスを気に掛ける必要があり、オブジェクトの状態の
変更を追跡する必要があるから	なのだろうか?
Page	89/120
値オブジェクト:永続化判断
実践ドメイン駆動設計では、前ページのチェック項目が
1:性質についての説明、2:Yes、3:Yes、4:No	であるなら、
値オブジェクトを使うべきとしています。
そして、オブジェクトを格納する場所としての永続化ストアは用意するが、
それがドメインモデル内の値の概念化に影響を及ぼさないようにすることが
重要としています。
ドメインモデルに、インフラストラクチャのデータモデルが漏れ出している。
ドメインモデルが、データモデルの単なる写像になっている。
Page	90/120
集約
集約(模範的説明)とは、
同一性をもつオブジェクトを含む集合を扱う設計パターン
関連が深くてライフサイクル(生成から破棄までの生存期間)が同じオブジェクトの
集合(Aggregates)から、	代表とするエンティティ(ルート)を選んでひと括りとし、
内部の操作はルートを経由しなければできないようにすることで、	ライフサイクル
の境界での一括したアクションを扱い易くします。
集約のインスタンスの永続化には、リポジトリを使います。
Page	91/120
集約の不変条件
集約は、
集約内にあるオブジェクトと集約全体に対して、不変条件を強制します。
不変条件が満たされることで、トランザクション制御ができるようになります。
不変条件とは、内容が意図した通りであり変更されていないことの保証です。
Page	92/120
集約の不変条件
集約全体の不変条件強制ロジック
集約は、集約内部のメンバ(エンティティと値オブジェクト)を集約の境界に定義
し、	外部から参照できないように隠蔽化します。
集約の境界内のメンバは、お互いと他の集約ルートのみ参照できます。
集約は、代表とするエンティティを一つ選び、ルートエンティティとします。
集約は、ルートエンティティのみが、集約外部のオブジェクトからアクセス可能と
し、	かつルートエンティティを経由しなければ、集約の境界内のメンバの操作も
できなくします。
集約は、ルートエンティティに集約の境界会内の不変条件をチェックする責務を
負わせます。
集約は、このようにして集約の境界内のメンバの意図しない変更を防ぎ、
不変条件(データの一貫性)が満たされるようにしています。
Page	93/120
リポジトリ
リポジトリ(模範的説明)とは、
ドメインモデルに同一性をもつオブジェクトの永続化の概念を導入する設計パタ
ーン
集約を使い、モデルのロックを可能にして、トランザクションを管理できるようにし
ます。	リポジトリにより、ドメインにインフラストラクチャの都合が漏れださないよう
にして、	ドメインロジックをコアドメインに集中できるようにします。
Page	94/120
リポジトリと永続化
リポジトリは、
集約を概念上の集合のように表現して、コレクションのように操作でき、
かつ背後でのDBへの永続化までできるようにしてくれます。
集約のオブジェクトの追加や削除が実行されると、
リポジトリの背後にある仕組みが、データベースに対して挿入や削除を行います。
こうして、ライフサイクルの始まりから終わりまでを通じて、	集約のルートに対する
アクセスとデータベースとの透過的同期を提供します。
Page	95/120
リポジトリのフロー例
抽象化したリポジトリのフロー例
クライアントから受けた選択条件をDBインターフェースに渡します。
DBインターフェースから受け取ったデータを集約に変換します。
(集約の生成にファクトリが介在する場合もある)
クライアントに集約のオブジェクトを返します。
Page	96/120
ファクトリ
ファクトリ(模範的説明)とは、
複雑なオブジェクトや集約のインスタンス生成責務を
別のオブジェクトに移すパターンです。
集約の各メンバが、自分の中核ロジックに集中できるようにするため、
集約全体をひとまとまりとして生成して、インスタンス生成の複雑さを隠蔽します。
Page	97/120
ドメインイベント
ドメインイベントは、
ドメイン内で発生した/する、何らかの出来事を捉えるためのものです。
メッセージングシステムを使い、何らかの操作を表すコマンドやクエリを、
境界づけられたコンテキストを超えてドメインモデル内の対応する専任者に通知
して、	対処してもらえるようにするパターンです。
Page	98/120
ドメインイベントの例
ドメインイベントのフロー例
実践ドメイン駆動設計	第8章	ドメインイベント	図8-1より
集約がイベントを作って出版し、
サブスクライバは、そのイベントを格納して、
リモートのサブスクライバに転送するか、格納せずに転送しています。
Page	99/120
ドメインイベントの導入検討条件
組織の文化によって注意すべきフレーズは代わりますが、
ディスカッションで、以下のようなフレーズが出たきた場合
ドメインイベントの導入を検討します。
何かのきっかけで、何かをしなければいけないことがキーポイント
「…するときに、」「もしそうなったら、…」
「…の場合は、私に知らせて欲しい」「…の場合は、通知して欲しい」
「…が発生したときに」
あるいは、
(社内の別システムの)あるドメインで発生したイベントを
別(システム)の境界づけられたコンテキストに通知しなければいけないとき。
Page	100/120
ドメインイベントの実現手法
ドメインイベントでは、
集約の変更成功のイベント通知により、
関係する他の集約のインスタンスの同期(別トランザクション)が行えるよう、
結果整合性(次の更新までに同期が保証できる)が図れる手法を利用します。
これは、イベントの他のコンテキストへの配送に時間がかかるためです。
結果整合性には、
スケーラブルかつシステム間を疎結合に保つメリットもあります。
結果整合性	(Eventual	Consistency)は、
データが更新された際には、即座にデータが反映されなくても、
参照時に更新結果が得られば良い…結果的に一貫性が保たれればよいという考
え方です。
Page	101/120
ドメインイベントのモデリング
イベントのモデリングの基本
イベントやプロパティの名前には、
イベント発生元の境界付けられたコンテキストのユビキタス言語に沿います。
イベントの名前には、実行されたコマンドを用いるのが適切です。
(コマンドがイベントの発生要因のため)
イベントの発生元や関連するプロパティを追加します。
イベントが発生した集約や、関係する他の集約(およびその識別子)
イベントを発生するために必要なパラメータ
イベントの発生による集約の状態の推移
イベントが提供するメソッド(挙動の操作)を追加します。
イベントの発生要因を表すプロパティを伝える目的操作
Page	102/120
ドメインイベントのモデリング
イベントのモデリングについての補足
イベントに追加する振る舞いは、副作用のないものにします。
イベントは基本的に不変クラスなのでシンプルになります。
Page	103/120
ドメインイベントのユースケース
ドメインイベントの一般的な使用例では、
パブリッシャー(出版)とサブスクライバー(購読)というパターンを使います。
集約が特定のイベントを作成し、それをパブリッシャーが発行(出版)して、	(シス
テムやコンテキスト境界をまたいだドメインモデルの)それを対象としたサブスク
ライバーが捕捉(購読)することで、特定のイベントに必要な対応を行ないます。
Page	104/120
ドメインイベントのコンポーネント
ドメインモデル内のイベントを扱うコンポーネント
パブリッシャー
パブリッシャーは、集約に対してシンプルなサービスを提供し、	集約がイベント
のサブスクライバに通知を送れるようにするための	軽量なオブザーバです。
ドメインモデルと同じモジュールに属します。
サブスクライバー
サブスクライバーは、対応するイベントが指定され、	イベントハンドリング(捕捉)
時の処理が実装された	軽量なオブザーバです。
一般的に、アプリケーションサービス(あるいはドメインサービス)から	パブリッシ
ャーに登録され、	イベントを発行する集約と同一のスレッドで実行されます。
Page	105/120
ドメインイベントのコンポーネント
ドメインモデル内のコンポーネントについての補足
ドメインモデルの情報をメッセージング基盤に漏らさないこと。
ドメインモデルからインフラストラクチャを間接的に利用することがあっても	明
示的に結合させてはいけません。
サブスクライバでは、指定されたものとは別の集約のインスタンスを取得して	状
態変更をしてはいけません。
Page	106/120
ドメインイベント:メッセージング基盤の利用
リモートにイベントを届けるためにはミドルウェアを使います。
リモートの境界づけられたコンテキストに、
手元のコンテキストで発生したイベントを届けるには、
一般的にミドルウェアに分類される、ActivieMQやRabbitMQやAkka…などの
メッセージング・コンポーネントを使います。
あるいは、RESTリソースを使った、独自のメッセージング・システムでも対応可
能でしょう。
Page	107/120
ドメインイベント:メッセージング基盤の整合性
モデルとイベントの整合性を保つ永続化の3パターン
1.	 ドメインモデルとメッセージ基盤の永続化共有
モデルへの変更と新しいメッセージの追加を、同一のローカルトランザクション
内で行えるよう、	ドメインモデルとメッセージング基盤が、永続化ストア(データソ
ースなど)を共有します。
欠点:メッセージングシステムのストレージ領域を	ドメインモデルと同じデータベ
ースに配置しないといけない。
2.	 ドメインモデルとメッセージ基盤の永続化のグローバル制御
モデルとメッセージングのストレージを別々にできるよう、	ドメインモデルの永続
化ストアとメッセージングの永続化ストアを、	グローバルなXAトランザクション
(二相コミット)で制御します。
欠点:グローバルなトランザクションを考慮しないといけない。
Page	108/120
ドメインイベント:メッセージング基盤の整合性
モデルとイベントの整合性を保つ永続化の3パターン
3.	 イベントストアの利用
イベントストアは、	モデルとイベントとの整合性が、単一のローカルトランザクシ
ョン内で保証されるよう、	イベント用の特別なストレージ領域(データベースの
テーブルなど)を、	ドメインモデルが使っているのと同じデータストア内に用意す
る手法です。
ストレージ領域は、境界づけられたコンテキストが所有して管理します。
外部のコンポーネントは、このイベントストアを使って、	格納済みのイベントのう
ちまだ発行していないものを、	メッセージングメカニズムを利用して発行します。
欠点:メッセージングメカニズムを経由して送信するために、	イベントをそのメカ
ニズムに転送する仕組みを自作しないといけません。
補足:イベントストアの基本役割は、シリアライズしたイベントをその発生順に保
持することです。
Page	109/120
ドメインイベント:イベントストアの主目的
イベントストアが提供できるもの
リモートのサブスクライバがイベントに反応できる。
イベントストアをメッセージング基盤を通してすべてのイベントを発行する際のキ
ューとすることで、	リモートのサブスクライバが自分のコンテキストの必要に応
じてイベントに反応できるようになります。
RESTベースの通知をクライアントに提供できる。
集約のコマンドの結果を完全に記録できる。
ドメインモデル上で実行された全てのコマンドの結果を履歴として記録できま
す。
データを使って、傾向の分析や今後の予測などを行なえる。
Page	110/120
ドメインイベント:イベントストアの主目的
イベントストアが提供できるもの
集約のインスタンスの再構築ができる。
リポジトリから取得した時系列のイベントを適用することで、集約のインスタンス
が再構築できます。
集約に対するある時点の変更を取り消せる。
取り消したい過去のある時点を指定して、	マークされたイベントを無視して、集
約のインスタンスの再構築を行います。
Page	111/120
サービス
サービス(模範的説明)とは、
ドメインの中核から外れるが、そのドメインに必要なタスクをこなす、
ステートレスな操作のこと。
どのオブジェクトにも属さいない操作のため、
オブジェクトとしてモデル化すると不自然ですが、
エンティティや値オブジェクトの責務としても不自然なので、
それ用の独立した操作インターフェース(メソッド)のみ提供します。
システムレベルのリモートプロシージャ呼び出し(RPC)や	メッセージ指向ミドルウ
ェアを使うような「サービス」のことではありません。
Page	112/120
サービスの種類
ドメインサービスは、
ドメインの中核から外れるが、そのドメインに必要なタスクをこなす、ステートレス
な操作	であり、	ビジネスロジックを持ち、アプリケーションサービスを使い、
多少複雑になることもある粒度が細かいタスクをこなします。
アプリケーションサービスは、
ビジネスロジックを持たないアプリケーション全体のロジックを提供し、
ドメインモデルのクライアントであり、ドメインサービスのクライアントにもなります。
Page	113/120
ドメインサービスの導入検討条件
ドメインサービスを使う(導入する)のを検討する条件は、
操作が、既存のエンティティや値オブジェクトに属さないとみなせる場合です。
以下のような条件が、考えられるそうです。
重要なビジネスロジックを実行する。
ドメインオブジェクトを、ひとつの構成から別の構成に変換する。
複数のドメインオブジェクトからの入力にもとづいて、値を算出する。
モデルの中核ではないが、そのモデルに不可欠な要件がある。
例:アカウント情報のパスワードは暗号化する。
アカウント情報に情報保管以外の暗号化という責務があることは、
単一責務の原則に違反しているためサービスに移します。
Page	114/120
ドメインサービスのモデリング
ドメインサービスのモデリングは、以下のようにシンプルです。
ドメインサービスのインターフェース宣言は、ドメインのモジュール内で行う。
ドメインサービスの実装は、(アプリケーションのモジュールなど)ドメインモデル
の外部に配置する。
ドメインサービスのセパレートインターフェースは、複数実装が必要でなければ
必須ではない。
操作名は、必ずユビキタス言語の一部(動詞)で命名すること。
状態を持たせないこと。
Page	115/120
モジュール
モジュール(模範的説明)とは、
Javaではパッケージと呼ばれている概念のこと。
DDDの文脈におけるモジュールに相当する。
DDDの文脈におけるモデル内のモジュールは、
ドメインオブジェクト内のひとまとまりのクラス群をまとめる、名前付きのコンテナ。
同じドメインオブジェクト内の他のモジュールのクラス群との結合を少なくするよう
設けます。
Page	116/120
モジュールの例
//	トップレベルのモジュール名	(一般的に所属先の逆インターネットドメイン名)
som.saasovation
//	境界付けられたコンテキストを表すモジュール名
//	実際のコンテキスト名と一字一句同じにする必要はない
com.saasoation.identiyaccess
com.saasovation.collaboration
com.saasovation.agilpm
//	ドメインのモジュール名
com.saasoation.identiyaccess.domain
com.saasovation.collaboration.domain
com.saasovation.agilpm.domain
//	ドメインモデルのモジュール名
com.saasoation.identiyaccess.domain.model
com.saasovation.collaboration.domain.model
com.saasovation.agilpm.domain.model
//	ドメインモデルのサービス名
com.saasoation.identiyaccess.domain.servis
com.saasovation.collaboration.domain.servis
com.saasovation.agilpm.domain.servis
Page	117/120
モジュールの例
//	ドメインモデル内のモジュール名
//	ドメインモデルのコンポーネントを配置する
com.saasovation.agilpm.domain.model.tenant
   		<<value	object>>	TenantId
com.saasovation.agilpm.domain.model.team
   		<<servis>>	MemberService
   		<<aggregate	root>>	ProductOwner
   		<<aggregate	root>>	Team
   		<<aggregate	root>>	TeamMember
com.saasovation.agilpm.domain.model.product
   		<<aggregate	root>>	Product
com.saasovation.agilpm.domain.model.product.backlogitem
   		<<aggregate	root>>	BacklogItem
com.saasovation.agilpm.domain.model.product.release
   		<<aggregate	root>>	Release
//	backlogitem	や	release	は、モデル内のモジュール内のモジュールを示す
Page	118/120
みなさん、お疲れ様でした。
この発表は、
エリックエバンスのドメイン駆動設計と、実践ドメイン駆動設計の
特徴的な一部のパターンの表層をなでただけです。
そして「意図の明白なインターフェース」のような、
細かいことですが重要な基本も抜けてしまっています。
ドメイン駆動設計は、もっともっと深いものです。
この発表が、何かのきっかけになりましたら幸いです。
Page	119/120
ご清聴、ありがとうございました。
Page	120/120

Loose and fluffy_ddd_intro