エリックエヴァンスのドメイン駆動設計を頑張って理解するためのメモ
モデル
モデルはビジネスドメインを表現する概念的な話。エンティティと値オブジェクトはドメインモデルの一種と言える。
エンティティ
一意な識別子を持つオブジェクトで永続性を持つことができる。
値オブジェクト
単一の値を表し、一意な識別子を持たない。
「a」とか10みたいなプリミティブな値を表現したオブジェクトだと思ってる。
プリミティブ型だけでは表現できないドメインロジックを表現するかつ、不変なオブジェクトとして扱うために値オブジェクトを使う利点がある。
今まで使ってきたレイヤーアーキテクチャに当てはめて考える
主にSpringのとき、データ層(Entity, Repository)、ドメイン層(service)、プレゼンテーション層(controller)的な三層レイヤーとかでやってたのでここで当てはめてみる。
- DDDの文脈で言うとエンティティはドメイン層のオブジェクト。
- リポジトリパターンで言うとドメイン層のエンティティをインフラストラクチャ層に渡す役割。なので、リポジトリのインターフェースはドメイン層に置き、実装はインフラストラクチャー層に置く。
- エンティティはドメインモデルであり、データベースに永続化されるため、リポジトリにそのまま引数として渡して良い。
- DTOはビジネスロジックを持たない異なるレイヤー間のやりとりに使われるので、一般的にアプリケーション層とプレゼンテーション層とのやりとりに使われる。
ChatGPTにSpringフレームワークにクリーンアーキテクチャ(オニオンアーキテクチャ)を適用したときにディレクトリ構成例を出力してもらった。
src/
├── main/
│ ├── java/
│ │ ├── com.example.yourapplication/
│ │ │ ├── application/
│ │ │ │ ├── dto/ (DTOクラス)
│ │ │ │ │ ├── UserInputDTO.java
│ │ │ │ │ └── UserOutputDTO.java
│ │ │ │ ├── UserService.java (アプリケーションサービス)
│ │ │ ├── domain/
│ │ │ │ ├── model/ (エンティティと値オブジェクト)
│ │ │ │ │ ├── User.java (エンティティ)
│ │ │ │ │ └── EmailAddress.java (値オブジェクト)
│ │ │ │ └── repository/ (リポジトリのインターフェース)
│ │ │ │ └── UserRepository.java
│ │ │ ├── infrastructure/
│ │ │ │ ├── db/ (データベースリポジトリの実装)
│ │ │ │ │ └── JpaUserRepository.java
│ │ │ └── interfaces/
│ │ │ ├── controller/ (コントローラ)
│ │ │ │ └── UserController.java
│ ├── resources/
│ │ ├── application.properties (アプリケーションの設定ファイル)
└── test/ (テストコード)
Entityをinfrastructure層に置いてたけど、ドメイン層なんだな、勉強になった。
レイヤーアーキテクチャとDDD
ChatGPTにクリーンアーキテクチャとDDDの関係について教えてもらった
ドメイン駆動設計(DDD)とクリーンアーキテクチャは、ソフトウェア開発における設計と実装のガイドラインを提供するものですが、それぞれ異なる視点を中心に設計原則を提供します。
DDDは主に、ビジネスのルールとドメインの知識をソフトウェアにどのように反映させるかに焦点を当てています。DDDの主な目的は、ビジネスの複雑さを理解し、それをソフトウェアの設計と実装に反映させることです。DDDは、ユビキタス言語、エンティティ、値オブジェクト、アグリゲート、ドメインイベント、リポジトリなどの概念を通じてこれを実現します。
一方、クリーンアーキテクチャは、ソフトウェアの構造と依存関係の管理に重点を置いています。クリーンアーキテクチャの主な目的は、ソフトウェアのテスト性、メンテナンス性、拡張性を向上させることです。これは、ビジネスロジックを中心に配置し、フレームワークやデータベースなどの詳細を外側の層に押し出すことで達成されます。
これら二つのアプローチは、お互いを補完する形で共存することができます。DDDの原則を用いてビジネスロジックを設計し、そのロジックをクリーンアーキテクチャの原則に従って組織化することが可能です。これにより、ビジネスの複雑さを適切にモデル化し、同時にソフトウェアの品質を維持することができます。
クリーンアーキテクチャとDDDはコンテキストが違うので上でやったDDDをレイヤーアーキテクチャに当てはめるのは無意味かもしれない。
結局のところ
ドメイン駆動設計はドメインを噛み砕いてチームに共通のモデルの概念をもたらす。そして、モデルを実装に結びつけるためにモデル駆動設計がある。モデル駆動設計はドメインを分散させず一箇所に集め、ドメイン部分を分離する。ドメインを隔離するのに一般的に広く普及したレイヤアーキテクチャが使われる。
DDDとはビジネスのドメイン知識を噛み砕き、チーム共通のモデルを実装に落とし込むためにさまざまな設計技法を使用してるという理解に落ち着いた。
ドメインの隔離に使われるレイヤアーキテクチャがクリーンアーキテクチャやオニオンアーキテクチャ、三層アーキテクチャなど様々あるのでDDDとレイヤアーキテクチャは共存できる。
ややこしいのがSpringやってるからだけどEntityとかRepositoryとかServiceという用語を使用して何かしらのレイヤーアーキテクチャで開発してきたから、DDDと同じ用語だけどコンテキストが違うので意味合いが違うみたいなことがたぶん起きている。
なので、SpringでDDDやろうとしてクリーンアーキテクチャ採用したいみたいなことをするとそれぞれの用語がぶつかってわけわかんなくなりそうなんだけど、そういうことじゃないの?
ユビキタス言語
ユビキタス言語とは、特定のプロジェクトやドメイン(ビジネス領域)における共通の言語や語彙のことを指します。これは、ソフトウェアのコード、設計文書、要件定義、ユーザーストーリー、会話など、プロジェクトのあらゆる側面で使われるべきです。
例えば、銀行のソフトウェアを開発しているとします。この場合、ユビキタス言語には「口座」、「預金」、「引き出し」、「振り込み」、「利息」など、銀行業界特有の語彙が含まれるでしょう。これらの語彙は、ソフトウェアの各部分で一貫した意味を持つべきです。
chatGPTの解答。ドメインエキスパートと開発者が共通したドメインモデルを扱うための名称みたいなものと理解。
メモというか感想
- DDDにおいて開発者はドメインに興味を持つ必要があるとされている。
- ドメインエキスパートと開発者の間に線を引かず、お互い共通のドメインモデルを作成するために話し合いを繰り返し行うことが大事
- それがDDDの大事な部分であり、ユビキタス言語がDDDの真髄というかコア的な概念と言われてるんだと思う。
- 今まで使用してきた用語たちがDDDで出てくるとおそらくコンテキストが違うので意味合いが違うのだけど頭がついていかない。