ドメイン駆動設計

**ドメイン駆動設計**（ドメインくどうせっけい、、**DDD**）は主要なソフトウェア設計手法の一つであり、ドメインエキスパートの言葉に基づき、ドメインにおけるプロセスやルールをよく表現したドメインモデルを構築し、それに基づいてソフトウェア開発を行うことに主眼を置くものである。

DDDは以下のような目的に基づく。

* プロジェクトにおける主な焦点を中核の業務領域と業務ロジックのレイヤーに置くこと
* 複雑な設計をドメインモデルで表現すること
* 技術者とドメインエキスパートの間にクリエイティブな協働関係を構築し、特定のドメイン問題を扱う概念的なモデルを継続的に洗練させること

DDDという名称は、による著書の中で初めて提唱されたものである。

## 概要
DDDは、多くの高水準な概念と実践を明確に示している。

もっとも重要なものは、ソフトウェアにおける「ドメイン」であり、これはユーザがプログラムを適用する対象領域を指す。戦術的設計の一つであるドメインモデルパターンにおいては、ソフトウェアの開発者は「ドメインモデル」を構築する。これは特定のドメインのある側面を表現し、ドメインにおける問題を解決するために用いることができるような抽象化のシステムである。

DDDは大きく**戦術的設計**と**戦略的設計**に分けられる。

戦略的設計では、同じ言葉、区切られた文脈という概念の導入と、事業活動をその性質によって複数の業務領域に分類することを行う。事業活動は、中核の業務領域（コアドメイン）、一般的な業務領域（ジェネリック・サブドメイン）、補完的な業務領域（サブドメイン）に分類される。

戦術的設計では、DDDにおける戦略を達成するために、具体的にどのように業務ロジックを表現し、ソフトウェアを実装するかという点についての議論を行う。業務ロジックの表現方法としては、トランザクションスクリプト、アクティブレコード、ドメインモデル、イベント履歴式のドメインモデルなどが挙げられる。

## 戦略的設計

### 言葉の意味と文脈
DDDにおいては、ドメインエキスパートと技術者間で同じ言葉を用いることによって、業務に対する共通理解を形成する。ただし、同じ事業領域内においても、背景が異なれば異なった意味を持つ言葉が存在する。この曖昧さを解消するために、DDDでは区切られた文脈という概念を導入する。

#### 同じ言葉（ユビキタス言語）
同じ言葉、あるいは**ユビキタス言語**（）とは、同じ言葉を使うことでドメインエキスパートと技術者間の効率的な意思伝達を促す、DDDにおける戦略的手法のことである。区切られた文脈内において、同じ言葉は同じ意味を持つ。DDDでは、技術者がドメインエキスパートと協力しながら同じ言葉を育て、特定のドメイン問題を扱うモデルの継続的な洗練を目指す。

ソフトウェアコード（e.g. クラス名、クラスメソッド、クラス変数）における言葉や構造はビジネスドメインに一致する。例えば、ソフトウェアがローン申請(loan application)を処理する場合、ソフトウェアは「loan application」「customer」といった名前のクラスや「accept offer」「withdraw」といったメソッドを持つことが考えられる。

#### 区切られた文脈（境界づけられたコンテキスト）
区切られた文脈、あるいは**境界づけられたコンテキスト**（）とは、同じ言葉に同じ意味を適用できる範囲のことである。区切られた文脈は、ソフトウェア設計の観点で、ソフトウェア技術者が決定する。

マーティン・ファウラーによれば、ドメインが大きくなるにしたがって、単一の統一されたモデルを構築することは難しくなる。これは、事業領域において、同じ言葉でも文脈によって異なる意味を持つ場合が出てくるためである。

DDDではシステム全体が単一の統一されたモデルを持つという考え方に反対し、システムを複数の区切られた文脈に分けることを推奨する。区切られた文脈はそれぞれが自らのモデルを持つ。計算機科学における難題は二つしかない。それはキャッシュの無効化と、命名である。ー フィル・カールトン区切られた文脈は言語学における「」に基づいているとされる。意味論的な領域とは、同じ言葉が同じ意味で使われる範囲のことを指し、例えば「トマト」が植物学的な文脈では「果実」である一方で、法的な文脈では「野菜」であるようなことが挙げられる。

### 業務領域の分類
DDDにおいて、ソフトウェアは中核の業務領域と、一般的な業務領域、補完的な業務領域に分けられる。DDDにおける重要かつ主要な目的の一つは、戦力を中核の業務領域に集中させることであるとされる。

あるソフトウェアにおいて中核の業務領域であっても、他のソフトウェアにとっては一般的な業務領域であることはあり得る。

#### 中核の業務領域
中核の業務領域（）は、プロジェクトのコアとなる複雑で重要なロジックを含む部分である。ドメインモデルなどの複雑な業務ロジックを扱うためのデザインパターン（戦術的設計）を選択することが考えられる。事業において戦略上強みとなる部分であり、頻繁な変更が考えられる。

#### 一般的な業務領域
一般的な業務領域（）はどのソフトウェアにおいても基本的にアプローチが変わらないような部分であり、したがって外部のソフトウェアやライブラリを活用することが考えられるとされる。例としては認証処理などが挙げられる。

#### 補完的な業務領域
補完的な業務領域（）は、事業活動を支えるものの、競争優位を生み出さない部分である。補完的な業務領域のロジックは単純かつ変更が少ないとされ、トランザクションスクリプトやアクティブレコードなどの簡易な業務ロジックの表現方法を用いることが適しているとされる。

## 戦術的設計
戦術的設計では、具体的にどのようにソフトウェアを実装するかという問題を取り扱う。以下はDDDにおける主要な技術方式である。

### 業務ロジックの表現方法
ヴラド・コノノフは、シンプルな業務ロジックに対する実装方法としてトランザクションスクリプトとアクティブレコード、複雑な業務ロジックに対するデザインパターンとしてドメインモデル、それを時系列に拡張したものとしてイベント履歴型のドメインモデルを挙げている。

#### トランザクションスクリプト
トランザクションスクリプト（）は手続き的な業務ロジックの実装方法であり、プレゼンテーション層から渡されるリクエストを処理する一連の流れの中で業務ロジックを表現する。

#### [[アクティブレコード|アクティブレコードパターン]]
アクティブレコード（）はドメインモデルの一種であり、モデルがDBのテーブルあるいはビューと一対一に対応する。アクティブレコードのオブジェクトはDBにおけるテーブルのレコードを表現し、レコードを表現するオブジェクト自身が永続化などのデータアクセス処理を行う。

アクティブレコードを用いるメリットとしては、構造がシンプルで、データベース操作が直感的になるということがある。アクティブレコードを用いた場合でも、業務ロジックはトランザクションスクリプトとして記述する。この場合、コードはDBを直接操作するのではなく、アクティブレコードオブジェクトを操作する。

アクティブレコードのデメリットとしては、テーブルとモデルが一対一に対応していることから、モデルがデータベースの構造に依存することと、ドメインモデルとしての柔軟性を欠くという点が挙げられる。

アクティブレコードの目的は、DB操作の最適化であるとされる。

#### ドメインモデルパターン
ドメインモデル（）は、業務ロジックとデータの両方を一体化させた、事業活動を表現するオブジェクトモデルである。ドメインモデルは他の層の知識に依存せず業務知識を表現することが望ましいとされ、その点で後述のポートとアダプタパターンと相性が良い。

典型的なドメインモデルは集約とそれを構成するエンティティ、値オブジェクト、ドメインサービスによって表現される。集約はドメインモデルの永続化におけるトランザクションの単位であり、業務ロジックはエンティティや値オブジェクトのフィールド、あるいはメソッドとして定義されるのに加え、それらに定義することが不自然であったり、ロジックが集約を跨いで存在する場合、これはドメインサービスによって表現される。

ドメインモデルが持つべき情報がドメインモデルの外に書かれており、業務知識が漏れ出している状態を、「ドメインモデル貧血症」と呼ぶことがある。

#### イベント履歴式のドメインモデル
イベント履歴式のドメインモデルでは、集約の状態変化をドメインイベントで表現する。ドメインモデルパターンでは集約の状態を永続化するのに対し、イベント履歴式のドメインモデルでは集約の状態の変化を表すドメインイベントを永続化する。

このパターンにおいては過去のある時点においての状態を得ることができるというメリットがある一方で、現在の状態を再現するために計算が必要になるというデメリットがある。これについては、テーブルが更新されるたびに最新の状態を投影したビューを更新し、CQRSパターンを用いて読み込みモデルからはこちらを参照することで対応できるとされる。

### アーキテクチャ方式

#### 階層化アーキテクチャ
ソフトウェアの階層化は情報技術において一般的な考え方の一つである。例えば、コンピュータネットワークの分野においては、OSI参照モデルが階層化アーキテクチャとして挙げられる。

アプリケーションレベルのソフトウェアアーキテクチャにおいては、以下に示すようないくつかのアーキテクチャパターンが知られている。

##### [[多層アーキテクチャ|レイヤードアーキテクチャ]]
古典的な三層レイヤードアーキテクチャでは、技術的な関心に基づいて、アプリケーションをプレゼンテーション層、ドメインロジック層、データアクセス層の三層に分ける。

##### ポートとアダプタ方式

ポートとアダプタ方式では、依存性の逆転を行うことによって、古典的レイヤードアーキテクチャにおけるドメインロジック層がデータアクセス層に依存することを回避する。この方式に基づいたアーキテクチャモデルとしては、オニオンアーキテクチャ、クリーンアーキテクチャ、ヘキサゴナルアーキテクチャが知られる。

これらのアーキテクチャは複数の層を持つ円として表現され、内層は外層の知識に依存しない。アーキテクチャの中心にはドメインロジックが存在し、中心のドメインロジックが他の何にも依存しないという性質から、これらのアーキテクチャを用いることによって、ドメインモデルが具体的なインフラストラクチャ層の知識に依存することを回避することができる。

クリーンアーキテクチャを提唱したによれば、奥に行くほどソフトウェアのレベルは高くなり、外層はメカニズムで、内層はポリシーであるとされる。

#### 依存性逆転の原則

#### CQRS（コマンドクエリ責任分離）

## 実装の選択
ドメインモデルパターンでは、開発者がドメインモデルを純粋で有用な構造として維持するためには、通常大量の分離とカプセル化を行う必要がある一方で、保守性などの利点を提供するため、Microsoftは、ドメインに対する共通理解を構築することで明確な利点のある複雑な業務領域にのみドメインモデルパターンを導入することを推奨している。

## ドメインモデルの構成要素
典型的なドメインモデルは集約とそれを構成するエンティティ、値オブジェクトに加え、ドメインサービスといった要素からなる。集約は複数のエンティティからなり、永続化においてデータの一貫性が必要とされるトランザクションの単位である。集約においてルートとなるエンティティが永続化におけるインターフェースとなる。例えば、BookとStockというエンティティがあり、これらがBook集約を形成しているとすると、ここでのルートはBookエンティティである。

エンティティは識別子によって同一性が識別され、エンティティや値オブジェクトによって状態が表現されるミュータブルなオブジェクトである。例えば、ほとんどの航空会社はすべてのフライトにおいて席に対して一意の数字を割り当てている。これは席の識別子である。一方で値オブジェクトは属性の組み合わせによって同一性が識別されるイミュータブルなオブジェクトである。例えば、ある人が名刺を交換する際を例に挙げると、この時名刺を交換する人は名刺の内容（属性）のみに関心があり、名刺一枚一枚を個別に扱うことはない。

ドメインサービスは、エンティティや値オブジェクトに実装することが不自然な業務ロジックを実装するためのステートレスなオブジェクトである。

集約の永続化には、リポジトリパターンが用いられることが一般的である。ここでのリポジトリは集約の入出力の単位のインターフェース（ポート）として用いられる。典型的なパターンでは、インフラストラクチャ層がドメインモデルのポートを実装し、ユースケースがリポジトリを用いて集約の出し入れを行う。

## 他の概念との関係

;オブジェクト指向分析設計: ドメイン駆動設計の考え方は、理論上、オブジェクト指向の手法に制約されるものではない。実際、ドメイン駆動設計では、オブジェクト指向の技法が実現する強みを活かそうとしている。
;モデル駆動工学（MDE）
;モデル駆動型アーキテクチャ（MDA）:  MDAの考え方は、ドメイン駆動設計と両立するが、二つの概念の意図するところは多少異なっている。MDAは、ドメインモデルをよりよく定義する方法よりも、技術の異なるプラットフォームに対してモデルをコードに変換する方法の方に関心がある。
;POJOとPOCO: POJOとPOCOは実装上の考え方であり、それぞれJavaと.NET Frameworkに固有のものである。しかし、POJOとPOCOという用語が現れたことは、二つのプラットフォームのいずれかにおいて、特定のテクノロジの要求に応じてではなく、純粋に対応するドメインの概念のビジネス上の振る舞いを実現するためにドメインオブジェクトが定義されるべきである、という考え方が広まりつつあることを示している。
;Naked Objectsパターン: このパターンは、次の二つの仮定に基づいている。

#良質なドメインモデルがあれば、ユーザインターフェイスは、単純にドメインモデルを反映したものになる。
#ドメインモデルを直接反映したユーザインターフェイスが必要であれば、より良いドメインモデルの設計を余儀なくされる。

;ドメイン固有言語（DSL）: ドメイン駆動設計は、必ずしもDSLを必要としないが、DSLを定義し、のような手法の実践を助ける。
;アスペクト指向プログラミング（AOP）: AOPを用いると、技術的な関心（セキュリティ、トランザクション管理、ロギング）をドメインモデルから簡単にくくりだすことができ、純粋にビジネスロジックに焦点をおいたドメインモデルの設計と実装を容易にする。

## ドメイン駆動設計をサポートするソフトウェアツール
ドメイン駆動開発の実践は、特定のソフトウェアツールやフレームワークに依存したものではない。しかし、多数のオープンソースツールとフレームワークがEvansの書籍で推奨しているパターンや、ドメイン駆動開発の方法をサポートしている。以下のようなものがある。

*Castle Windsor/MicroKernel：マイクロソフトの.NET Framework向けの制御の反転/依存性の注入コンテナであり、サービスとリポジトリ、ファクトリーを利用者に提供する。
*Cosmos：ドメイン駆動設計の、中でもAOPの実践をサポートした、アプリケーションフレームワーク。
*DataObjects.Net：データベースアプリケーションのフレームワーク/開発環境であり、オブジェクト関係マッピングとドメイン駆動開発をサポートしている。
*Domdrides：ドメイン駆動設計をJavaで実現する際に有用なライブラリ。
*ECO：CapableObjects社によるUML図からのデータベース、コード、状態マシンの生成を行うフレームワーク。
*Flow：PHPのアプリケーションフレームワークで、ドメイン駆動開発を中心においている。良質なドメインモデルの形成を促し、またリポジトリ、エンティティ、値オブジェクトをサポートする。また依存性の注入、AOPのフレームワークを提供している。
*Habanero.NET（Habanero）：オープンソースのドメイン駆動開発の原則を用いてエンタプライズアプリケーションを開発するためのエンタプライズアプリケーションフレームワークで、.NET Framework上に実現されている。
*ManyDesigns_Portofino：ManyDesigns Portofinoはオープンソースのモデル駆動型のWebアプリケーションフレームワークで、高い生産性とメンテナンス性を目標にしている。CRUDフォーム、関係、ワークフロー管理、ダッシュボード、パンくずリスト、検索、シングルサインオン、権限、レポートなどを提供する。
*NakedObjectsFramework、Apache Isis：naked objectsパターンを実現しており、依存性の注入をサポートしている。またドメイン駆動設計におけるリポジトリ、ファクトリー、サービスの概念を、再利用可能な形で実装している。
*NReco：軽量なオープンソースの.NET向けドメイン固有のMDDを行うフレームワークである。JQuery、Open NIC.NET、OGNL、Log4Net、Lucene.NET、SemWebなどと結合されている。
*OpenMDX：Jakarta EE、.NETをサポートするオープンソースのJava向けMDAフレームワークである。OpenMDXは典型的なMDAフレームワークとは異なり、「実際のシステムの振る舞いを直接操作するためにモデルを使用する」。
*OpenXava：はJPAのエンティティからAjaxアプリケーションを生成する。実行可能なアプリケーションを作成するために、ドメインクラスを記述するだけでよい。
*Roma Meta Framework：ドメイン駆動開発を中心においたフレームワークで、新しい全体的な方法により、設計者・開発者がGUI、国際化、永続化など、何もかもPOJOとして見えるようにする。
*Sculptor:ドメイン駆動開発の用語を用いるコード生成フレームワーク。
*Sculpture - Model Your Life：オープンソースのモデル駆動開発のコード生成ツールの中で、Sculpture は最も強力なものの一つである。単純なCRUDアプリケーションから、複雑な大規模アプリケーションまで、SculptureはNHibernate、Entity Framework、WCF、CSLA、Silverlight、WPF、ASP.NET MVC などの一般的なフレームワークのための型をあらかじめ用意している。
*Strandz：ドメイン駆動のフレームワークで、アプリケーションのUI層と、ドメイン層双方の実装に非依存である。プログラマーは、特殊なクラスを用いてアプリケーションのワイヤモデルを記述する。
*TrueView for .NET：モデル駆動開発とnaked objectsをサポートした簡単に使用できるフレームワークで、これからモデル駆動開発を開始しようというチームに向いている。
*ASP.NET Boilerplate：ドメイン駆動開発のWebアプリケーション作成フレームワークで、N層レイアのアプリケーション開発が可能となっている。名称からも分かるようにマイクロソフトの.NET Frameworkの技術の上に構築されている。

## 脚注

### 注釈

### 出典

## 関連項目

* コードベース - ドメイン駆動設計を用いることによって、業務ロジックのコードベースを効率的に管理することができる。
* ソフトウェア開発哲学の一覧

## 外部リンク
* Eric Evans on Domain Driven Design - Putting the Model to Work
* Eric Evans on Domain Driven Design - Strategic Design
* Jimmy Nilsson on Domain Driven Design