🎛️
アプリケーションサービス(Application Service)
ユースケースを調整するオーケストレーション層。ドメインロジックは含まず、薄く保つ
解決する課題
UI・API・メッセージキューからのリクエストがドメインモデルに直接触れると、インフラの詳細(HTTP・トランザクション・認証)がドメインに混入する。また、複数のドメインオブジェクトを使うユースケースの調整をどこに書くかが不明確になる。
概念
アプリケーションサービスは、ユースケース1つを1メソッドで表現する薄い調整レイヤー。
責務は:
- リポジトリから集約を取得する
- ドメインサービス・集約のメソッドを呼び出す
- リポジトリに集約を保存する
- ドメインイベントを発行する
ドメインのビジネスルールは持たない。持つのは「何を、どの順で呼ぶか」という調整だけ。
例
class PlaceOrderApplicationService:
def __init__(
self,
order_repo: OrderRepository,
product_repo: ProductRepository,
event_publisher: DomainEventPublisher,
):
self._order_repo = order_repo
self._product_repo = product_repo
self._publisher = event_publisher
def place_order(self, command: PlaceOrderCommand) -> OrderId:
# 1. 集約を取得
order = self._order_repo.find_by_id(OrderId(command.order_id))
if not order:
raise ApplicationException("注文が見つかりません")
# 2. ドメインメソッドを呼び出す(ルールはここにない)
order.place()
# 3. 保存
self._order_repo.save(order)
# 4. イベント発行
for event in order.pop_events():
self._publisher.publish(event)
return order.id
薄いサービス層の原則
# ❌ ビジネスロジックがアプリケーションサービスに漏れている
class OrderApplicationService:
def place_order(self, order_id: str) -> None:
order = self._repo.find_by_id(order_id)
if len(order.items) == 0: # ドメインルールがここにある!
raise Exception("商品がない")
if order.status != "DRAFT": # ドメインルールがここにある!
raise Exception("確定済み")
order.status = "PLACED" # 直接状態を変えている!
self._repo.save(order)
# ✅ ドメインロジックは集約に委譲
class OrderApplicationService:
def place_order(self, order_id: str) -> None:
order = self._repo.find_by_id(order_id)
order.place() # ルールは Order エンティティが知っている
self._repo.save(order)
コマンドオブジェクト
引数を1つのコマンドオブジェクトにまとめると、シグネチャが安定する。
@dataclass
class PlaceOrderCommand:
order_id: str
requested_by: str # 認証情報
ドメインサービスとの違い
| アプリケーションサービス | ドメインサービス | |
|---|---|---|
| ドメインルールを含むか | 含まない | 含む |
| インフラへの依存 | あり(Repository・Publisher) | 最小限 |
| ユビキタス言語 | 薄く使う | 強く使う |
関連概念
- → ドメインサービス
- → 六角形アーキテクチャ(アプリケーションサービスはポートの実装)
- → ドメインイベント
- → CQRS
- 1. 🗺️サブドメイン(コア・サポート・汎用)
- 2. 🗾コンテキストマップ
- 3. ⬡六角形アーキテクチャ(ポートとアダプター)
- 4. 🪪エンティティ(Entity)
- 5. ⚙️ドメインサービス(Domain Service)
- 6. 📣ドメインイベント(Domain Event)
- 7. 🫧集約(Aggregate)
- 8. 📐集約の設計原則(Vernon の4ルール)
- 9. 🗄️リポジトリ(Repository)
- 10. 🏭ファクトリ(Factory)
- 11. 📦モジュール(Module)
- 12. 🎛️アプリケーションサービス(Application Service)
- 13. 🔌境界づけられたコンテキストの統合
- 14. ⚡CQRS(コマンドクエリ責任分離)
- 15. 📜イベントソーシング(Event Sourcing)
出典: 実践ドメイン駆動設計(Vaughn Vernon)第14章