GoF以外のプログラミング・デザインパターン #13 Domain Service / Application Service

2025/12/04

プログラミング 学習

t f B! P L
eyecatch Entity / ValueObject / Repository / Aggregate を理解したうえで、「Service(サービス)」の役割を押さえると、DDD(ドメイン駆動設計)の全体像が一気にクリアになります。 そのServiceパターンそのモモについてと、の2種類の特色について紹介します。

Serviceとは何か?

Service(サービス) は「オブジェクトの振る舞いを外に出したもの」です。 Entity や ValueObject に属さないロジックを扱うための補助的な役割パターンです。

2種類のServiceパターン

種類 主な責務 どこに属するか
Domain Service(ドメインサービス) ビジネスロジックの中核 ドメイン層 購入金額の割引計算、在庫引当、決済処理など
Application Service(アプリケーションサービス) ユースケースの調整・外部入出力 アプリケーション層 コントローラからドメインを呼び出し、結果を返す

① Domain Service(ドメインサービス)

ドメインサービスには次のような特徴があります。
・複数のエンティティや値オブジェクトに関わるビジネスルールをまとめる場所。 ・ビジネス上の「動作」を表すが、状態(プロパティ)は持たない。 ・エンティティの責務にすべきでない、横断的なロジックを担当。

サンプルコード

注文と在庫をまとめて扱うサービス class StockService { constructor(stockRepository) { this.stockRepository = stockRepository; } canPurchase(productId, quantity) { const stock = this.stockRepository.findByProductId(productId); return stock && stock.amount >= quantity; } decreaseStock(productId, quantity) { const stock = this.stockRepository.findByProductId(productId); stock.amount -= quantity; this.stockRepository.save(stock); } }

ポイント解説

StockService は「ビジネスロジック」を扱うクラス。 ただし、UIやDB接続には関知しない。 エンティティに属さない「在庫引当」「料金計算」などをまとめる役割。

② Application Service(アプリケーションサービス)

アプリケーションサービスには、次のような特徴があります。
・ユースケース(アプリ全体の操作の流れ)を制御する層。 ・コントローラやAPIなどの外部インターフェースと、ドメイン層(Entity / Repository / DomainService)をつなぐ。 ・ビジネスロジック自体は持たない。

サンプルコード

注文処理のアプリケーションサービス class OrderApplicationService { constructor(orderRepository, stockService) { this.orderRepository = orderRepository; this.stockService = stockService; } placeOrder(customerId, productId, quantity) { // 1. 在庫確認(ドメインサービスを利用) if (!this.stockService.canPurchase(productId, quantity)) { throw new Error("在庫不足です"); } // 2. 注文作成(エンティティ) const order = new Order(Date.now(), customerId); order.addItem(productId, quantity); // 3. 在庫減少(ドメインサービス) this.stockService.decreaseStock(productId, quantity); // 4. 永続化(リポジトリ) this.orderRepository.save(order); return order; } }

ポイント解説

アプリの流れ(ユースケース)を記述する場所。 ビジネスルール(割引計算など)はDomainServiceに委譲。 コントローラなどから直接呼び出される。

関係性まとめ(全体図)

[ Controller / API ] ← ユーザー操作 │ ▼ [ Application Service ] ← ユースケース制御 │ ▼ [ Domain Service ] ← ビジネスルール(ドメイン知識) │ ▼ [ Entity / Value Object / Repository ] ← データモデル

違いのまとめ

観点 Domain Service Application Service
目的 ビジネスルールの表現 ユースケースの流れ制御
属する層 ドメイン層 アプリケーション層
状態 持たない 持たない
呼び出し元 Application Service Controller / API
依存先 Entity, ValueObject, Repository DomainService, Repository
割引計算、在庫確認、決済処理 注文受付、ユーザー登録、メール送信

あとがき

普通にClassを作成して、constructorでnewインスタンス起動する処理を設けた場合の基本記述っぽいですが、 Domainサービスも、Applicationサービスも、実際の処理を持たないという点で、受け渡しをするクラスという意味合いが強いようです。 MVCのコントローラに改装を持たせるなら、上位に設置するクラスのようなイメージが持てますね。 色々なデザインパターンと組み合わせて使える基本的なサービスと言うパターンが理解できました。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ