ddd-domain-service について
ドメインの振る舞いを、エンティティなどではなくステートレスなドメインサービスに置く判断を支援するスキルです。ドメイン処理、アプリケーション層のオーケストレーション、インフラ処理を区別します。
主な機能
- 01ドメインサービスの適用条件
- 02三つのサービス層の区別
- 03ドメイン操作の命名指針
- 04状態と責務範囲の判断
- 05サービスのアンチパターン
活用シーン
- 01複数の集約にまたがる操作の調整
- 02適切なエンティティがない計算のモデル化
- 03ユースケース制御とドメイン処理の分離
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-domain-serviceインストール後、Claude Code で/ddd-domain-serviceを入力して読み込まれたか確認します。
詳細
1 行での要約
ドメインサービスとは、ドメイン層におけるステートレスな操作であり、単一のエンティティや値オブジェクトに自然に属さないものです。通常、複数の集約を調整する場合や、特定の対象に結び付かないドメイン上の計算を行う場合に該当します。
このスキルを使う場合
- まとまりのあるドメイン操作が複数の集約に関わる場合(例:2 つの
Account集約間で送金する)。 - ドメイン型を使った計算だが、その型のいずれかのメソッドにするのが自然ではない場合(例:為替レートを使った通貨換算)。
- 参加するエンティティのいずれかに振る舞いを無理に持たせると、そのエンティティがほかのエンティティについて「知りすぎる」ことになる場合。
このスキルを使わない場合
- ロジックを単一のエンティティに自然に持たせられる場合は、そのエンティティに実装します。
- ユースケースの処理、トランザクションの開始、リポジトリの呼び出しなど、アプリケーション層でのオーケストレーションを行う場合は、ドメインサービスではなくアプリケーションサービスです。
- HTTP 呼び出し、データベースアクセス、メッセージ送信など、インフラストラクチャに関わる処理を行う場合は、インフラストラクチャサービスです。
中核となる内容
DDD のコードベースでは、次の 3 種類のサービスが共存することがよくあります。それぞれを区別してください。
ドメインサービス。 ドメイン層に置きます。ドメイン型のみを操作します。ステートレスです。ユビキタス言語における動詞を表現します。たとえば TransferService.transfer(fromAccount, toAccount, amount) は適切ですが、AccountUtils.handleTransfer(...) は適切ではありません。
アプリケーションサービス。 ユースケースをオーケストレーションします。トランザクションを開始し、リポジトリを呼び出し、ドメインサービスを実行し、イベントをディスパッチします。ステートレスです。アプリケーション層に置きます。
インフラストラクチャサービス。 外部システムと通信します。HTTP リクエストの送信、データベースへの書き込み、キューへの公開などを行います。インフラストラクチャ層に置きます。
ドメインサービスには、ドメインの観点で何をするのかを表す名前を付けます。TransferService や ExchangeRateConverter は適切な名前です。TransferManager や TransferHelper は好ましくありません。技術的なノイズによって動詞が見えにくくなるためです。
判断の目安
- エンティティの振る舞いを優先します。複数の集約に関わる操作や、自然な配置先がない操作に限ってドメインサービスを使います。
- ドメインサービスに状態がある場合、分類が誤っている可能性が非常に高いため、ドメインエンティティや値オブジェクトにするか、状態を参加する集約のいずれかに移します。
- ドメインサービスが数十のメソッドを持つようになった場合、実態は「トランザクションスクリプト」かもしれません。分割するか、振る舞いをエンティティに戻します。
アンチパターン
- すべてのクラスに
*Serviceの接尾辞を付けること。ドメインがデータ DTO に対するトランザクションスクリプトの集合になります(ddd-anti-patternsの貧血ドメインモデルを参照)。 - ドメインサービスにインフラストラクチャ(データベース、HTTP)を含めること。ドメインがデプロイ上の関心事と結合します。
- エンティティのメソッドを経由せずに、渡されたエンティティを変更するドメインサービス。エンティティの不変条件を迂回します。
- キャッシュ、セッション、その他のプロセス状態を保持する、状態を持つ「サービス」。
関連項目
ddd-entity— 振る舞いを配置する先として、まず検討します。ddd-aggregate— ドメインサービスは集約間の調整を行うことがよくあります。ddd-anti-patterns— 貧血モデルやサービスの増殖に関する問題を参照してください。
参考文献
- Evans, Domain-Driven Design(2003 年)、第 5 章(ソフトウェアで表現されたモデル)。