はじめに
DDDの勉強を始めてみたものの初見の用語がバンバン出てきて心が折れそうになったので、雑にまとめてみました。
「雑だけどなんとなく分かる」を優先しているので一部正確ではない表現があるかもですがご容赦ください。
(航空監視システムの話がちょくちょく出ているのはDDD Quicklyの例でよく使われていたためです。)
全体的な話
ドメイン
システム化しようとしている現実世界の万物です。
例えば航空監視システムを作ろうとしているなら、航空監視に必要な人・モノ・情報・業務・etc...です。
当然これら全てをシステムに落とし込むことはできません。
ドメインモデル
システムに落とし込めるよう、ドメインをシンプルに捉え直した(=モデリングした)ものです。
ドメインに詳しい人(その業務の担当者等)とエンジニアで共同で作ります。
モデリングの手法についてはググってみたらたくさん出てくるので調べてみましょう。
例えば↓
・モデルでドメイン知識を表現するとは何か[DDD]
・リレーションシップ駆動要件分析(RDRA)
・teruuuのブログ - ユースケース駆動開発
ドメインロジック
ドメインモデルをコードに落とし込んだものです。
DDDではドメインモデルとドメインロジックは相互に同期が取れているものとしています。
伝統的なウォーターフォールの開発プロセスがドメイン→モデル→コードの一方通行なのに対し、
DDDのプロセスはドメイン→ドメインモデル⇄ドメインロジックという感じです。
ユビキタス言語
「ドメイン→ドメインモデル⇄ドメインロジック」の枠組みの中で、同じ概念は同じ言葉で表現して、モデル内でもコード内でもどこでも齟齬なく使えるようにしましょうという思想です。(ユビキタス=遍在、普遍、どこでも使える)
特にドメインに詳しい人と実際にシステムを作るエンジニアの間で使用する言葉に乖離が生じやすいので注意が必要です。例えば、ドメインに詳しい人は「航路」と言っているのを、エンジニアは「ルート」という言葉で表現したり。この乖離が発生するとドメインモデルを共同で作れなくなってしまうので、「飛行機が進む道のことは『ルート』と呼びましょう」と共通認識を取っておくのです。
コンテキスト境界
1つのチームが対処する「ドメイン→ドメインモデル⇄ドメインロジック」の範囲のことです。この中でユビキタス言語を確立していくので、例えば自分のチームが指している「ルート」と隣のチームが指している「ルート」は異なることが多いです。逆に言うとコンテキスト境界がしっかり定まっているおかげで、他チームがどのように開発しているのかを気にしなくて済むようになります。
コードの話
エンティティ
オブジェクト(=クラス)です。ドメインモデルに登場するオブジェクト(人とかモノとか)をコードに落とし込んだものです。適切な値(フィールド)と振る舞い(メソッド)を与えます。
エンティティは状態を保持し(ステートフル)、識別子(キー値)によって一意に特定されます。
航空監視システムだと滑走路とかがこれに該当するんだと思います。その滑走路が利用可能かの状態を保持していると思われるので。
バリューオブジェクト
オブジェクト(=クラス)です。ドメインモデルに登場するオブジェクト(人とかモノとか)をコードに落とし込んだものです。適切な値(フィールド)と振る舞い(メソッド)を与えます。
バリューオブジェクトは状態を保持せず(ステートレス)、値は不変(イミュータブル)です。
航空監視システムだと飛行機のスペック(搭載しているエンジン種別とか最大収容人数とかの情報)とかがこれに該当するんだと思います。飛行機のスペックが刻々と変化するわけはないので。
※エンティティとバリューオブジェクトの違いについては↓こちらが参考になります。
DDD基礎解説:Entity、ValueObjectってなんなんだ
サービス
エンティティやバリューオブジェクトに含めることが不自然な振る舞い(メソッド)を集約したクラスです。
例えば、「次いつその滑走路が使われるのか」は、滑走路オブジェクトも飛行機オブジェクトも預かり知らない領域です。そういう場合に、それを判定するための処理をサービスとして切り出します。
モジュール
巨大なモデルを理解するために複数のクラスを類似の役割で集約した仮想的なまとまりです。
モジュール間の相互関係を理解することでコンテキストの理解を容易にすることができます。
一方、モジュール内の詳細な挙動を理解したい場合には個々のクラスを見ていくことになります。
複数のチーム(≒複数のコンテキスト)が絡む話
コンテキストマップ
コンテキスト同士の関係性を図示したものです。
共有カーネル
1チーム1コンテキストでしっかり境界を定めるのが理想ですが、実際問題、複数のチームが重複した部分の実装を担わざるをえない場合もあります。そういう時は仕方ないので「ここは共有部」と明確にして、慎重な変更・徹底した情報共有をしましょう、というプラクティスです。
カスタマ-サプライヤ
コンテキスト間に依存関係が発生している場合、依存している側がカスタマ(顧客)、依存されている側がサプライヤ(供給者)の役割を演じると開発が円滑に進むよ、というプラクティスです。基本的にカスタマがサプライヤに要求を出し、サプライヤはそれを満たすような実装を行うというものです。
防腐レイヤ
外のコンテキストとやり取りをする際に影響を受けないよう、防腐層(変換層)を噛ませるプラクティスです。DDDで開発されたもの同士を統合する場合だけでなく、レガシーシステムとの統合を迫られている際にも有効です。
DDDを理解するためのポイント
DDDの勉強で詰まりがちなのが「今何の話をしているのか分からない」という部分だと思います。なにせDDDと一口に言っても扱っている範囲が膨大なので(これがDDD初心者が挫折しやすい原因だと個人的には思っています...)。そこで、
- 今は「モデリング(ドメイン→ドメインモデル)」の話か、それとも「コーディング(ドメインモデル⇄ドメインロジック)」の話か
- 今は「クラス(オブジェクト)」「モジュール(複数のクラス)」「単一コンテキスト(複数モジュール)」「複数コンテキスト」のどのサイズでの話か
の観点で「今何の話をしているのか」を整理しながら読み進めると、少しは理解しやすいのではないかと思います。
- | クラス | モジュール | 単一コンテキスト | 複数コンテキスト |
---|---|---|---|---|
モデリング | - | クラス図 シーケンス図 |
ユビキタス言語 ユースケース図 |
システムマップ |
コーディング | エンティティ バリューオブジェクト |
アグリゲート リポジトリ |
ユビキタス言語 オニオンアーキテクチャ |
共有カーネル 防腐レイヤ |
おわりに
他にもDDDでしか見かけない言葉はたくさんありますが、頻出どころはこれで抑えられたのではないでしょうか。
次のステップとしてこの辺の本を読んでもある程度耐性ができていると思います。