1. DDD(ドメイン駆動設計)とは?
DDD(Domain-Driven Design、ドメイン駆動設計)は、複雑なビジネスロジックを扱うシステムを効果的に設計する手法です。特に、開発者とビジネス側が共通の認識を持ち、保守性や拡張性を向上させることを目的としています。
2. エンティティと値オブジェクトの違い
エンティティ(Entity)
エンティティは 一意の識別子(ID)を持ち、状態が変化するオブジェクト です。
特徴
- IDを持つ(同じIDなら同じエンティティとみなす)
- 状態が変化する(例: 注文の状態が「支払い待ち」→「配送中」→「完了」)
- 等価性の判断はIDで行う
例(Java)
public class User {
private final Long id;
private String name;
private String email;
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public void changeEmail(String newEmail) {
this.email = newEmail;
}
public Long getId() {
return id;
}
}
値オブジェクト(Value Object)
値オブジェクトは IDを持たず、不変(Immutable)な値を表すオブジェクト です。
特徴
- IDを持たない(同じ値なら等しいとみなす)
- 不変(Immutable)(変更不可、変更する場合は新しいオブジェクトを作成)
- 等価性はすべてのフィールドの値で判断
例(Java)
public class Money {
private final BigDecimal amount;
private final String currency;
public Money(BigDecimal amount, String currency) {
this.amount = amount;
this.currency = currency;
}
public Money add(Money other) {
if (!this.currency.equals(other.currency)) {
throw new IllegalArgumentException("通貨が異なるため加算できません");
}
return new Money(this.amount.add(other.amount), this.currency);
}
}
3. 値オブジェクトとドメインサービスの棲み分け
値オブジェクトに入れるべき処理
- 値そのものの操作(例:
Money.add()
) - そのオブジェクトの性質に関わる処理
- 不変であるべき処理
ドメインサービスに入れるべき処理
- 複数のエンティティ・値オブジェクトを組み合わせる処理
- 外部データを参照する処理(例: 為替レート取得)
- あるエンティティの責務として持つのが不自然な処理
例: 通貨変換(ドメインサービス)
public class ExchangeRateService {
private final ExchangeRateRepository exchangeRateRepository;
public ExchangeRateService(ExchangeRateRepository exchangeRateRepository) {
this.exchangeRateRepository = exchangeRateRepository;
}
public Money convert(Money from, String targetCurrency) {
if (from.getCurrency().equals(targetCurrency)) {
return from;
}
BigDecimal rate = exchangeRateRepository.getRate(from.getCurrency(), targetCurrency);
BigDecimal convertedAmount = from.getAmount().multiply(rate);
return new Money(convertedAmount, targetCurrency);
}
}
4. リポジトリとサービスの棲み分け
リポジトリ(Repository)の役割
- データの永続化(保存・取得)
- データベースアクセスのカプセル化
- CRUD操作のみ(ビジネスロジックは持たない)
ドメインサービス(Domain Service)の役割
- ビジネスロジックを実装
- 複数のエンティティや値オブジェクトを操作
アプリケーションサービス(Application Service)の役割
- ユースケースを管理
- トランザクション管理
- DTO変換(クライアントとのデータ変換)
まとめ
DDDでは、エンティティ、値オブジェクト、リポジトリ、ドメインサービス、アプリケーションサービスがそれぞれ異なる役割を持ちます。適切な責務分離を行うことで、保守性・拡張性の高いシステムを構築できます。
- エンティティ はIDを持ち、状態が変化するオブジェクト。
- 値オブジェクト はIDを持たず、不変な値の概念を表す。
- リポジトリ はデータの永続化を担当し、ビジネスロジックを持たない。
- ドメインサービス は複数のエンティティをまたぐビジネスロジックを管理する。
- アプリケーションサービス はユースケースの流れを管理し、リポジトリやドメインサービスを調整する。
これらの設計原則を意識することで、システムがスケーラブルかつ理解しやすくなり、変更に強い構造を実現できます。