ドメイン駆動設計(DDD)を学んでいると、ドメインメソッドは副作用を起こすために呼び出すものなのか、それとも戻り値を利用して処理を組み立てるものなのかという疑問が出てきます。特に業務処理では、データ保存、帳票作成、後続処理など複数の結果を扱う必要があり、設計方針に迷うことがあります。この記事では、DDDにおけるドメインメソッドの役割や戻り値の扱い、副作用との関係について具体例を交えて解説します。
DDDのドメインメソッドは副作用だけを目的にするものではない
ドメイン駆動設計におけるドメインメソッドは、単純に副作用を発生させるためだけのものではありません。重要なのは、そのメソッドが表現する業務ルールをどこに置くかという点です。
例えば「出庫する」という処理の場合、出庫可能かどうかの判定、在庫数量の変更、出庫状態の変更などはドメインの責務になります。これらをドメインオブジェクト自身に持たせることで、業務知識をコード上で表現できます。
一方で、帳票出力や外部システムへの通知などは、必ずしもドメインモデル自身が担当する必要はありません。ドメインモデルは業務状態の変更や判断に集中させることが一般的です。
戻り値を利用する設計はDDDでも問題ない
ドメインメソッドの戻り値を利用して後続処理を行うことは、DDDの考え方に反するものではありません。
例えば出庫処理で、出庫メソッドが出庫結果や発行すべき帳票情報を返す設計は十分に考えられます。
具体例として、以下のような結果を返すことがあります。
- 確定した出庫番号
- 出庫対象の商品情報
- 在庫更新後の状態
- 発行が必要な帳票の種類
- 後続処理に必要な業務イベント情報
このような戻り値は、ドメインで発生した事実を外部へ伝える役割を持ちます。
ドメイン層で避けたいのは不要な外部副作用
DDDで問題になりやすいのは、ドメインメソッドの中でデータベース保存や帳票印刷、メール送信などの外部処理を直接実行してしまうケースです。
例えば、以下のような実装はドメインオブジェクトの責務が大きくなりすぎます。
「出庫する」というメソッドの内部で、在庫を変更し、そのままDBへ保存し、PDF帳票を生成し、配送システムへ通信するという処理をすべて行う設計です。
このような設計ではテストが難しくなり、業務ルールの変更とインフラ変更が強く結びついてしまいます。
保存結果を使って帳票出力する場合の設計例
出庫情報の保存結果を利用して帳票を出力したい場合は、アプリケーションサービス層で処理を調整する設計が一般的です。
例えば以下のような流れになります。
- アプリケーションサービスが出庫処理を呼び出す
- ドメインモデルが出庫可能か判断して状態を変更する
- ドメイン処理の結果として出庫情報を返す
- アプリケーションサービスが保存や帳票出力を実行する
- 必要に応じて配車処理などへ連携する
この場合、ドメインは業務判断を担当し、処理の流れを管理する部分はアプリケーション層が担当します。
複数の戻り値が必要になる場合の考え方
複雑な業務処理では、戻り値が1つでは足りないケースがあります。その場合でも、無理に複数の値を返す必要はありません。
よく使われる方法として、処理結果を表現する専用のオブジェクトを作成する方法があります。
例えば「出庫結果」というクラスを作り、その中に出庫番号、更新後の商品情報、発生した業務イベントなどをまとめます。
これはDDDでよく利用される値オブジェクトやDTOの考え方にも近く、意味のある単位で結果を表現できます。
ドメインイベントを使う方法もある
処理結果を複数の場所で利用したい場合は、ドメインイベントという考え方も有効です。
例えば出庫が完了した場合、「出庫完了イベント」を発行し、それを購読する処理が帳票作成や配車処理を担当します。
この方法では、出庫という業務上の事実と、その後に発生する処理を分離できます。
ただし、すべての処理をイベント化すれば良いわけではありません。単純な処理であれば、戻り値を利用したほうが理解しやすい場合もあります。
DDDで大切なのは副作用か戻り値かではなく責務の分離
DDDにおいて重要なのは、ドメインメソッドを副作用専用にすることではありません。
大切なのは「その処理はどの層やオブジェクトが責任を持つべきか」を判断することです。
業務ルールや状態変更はドメインモデルに置き、処理の流れや外部システムとの連携はアプリケーション層などに分離すると、変更に強い設計になります。
まとめ|DDDでは戻り値と副作用を適切に使い分ける
ドメイン駆動設計のドメインメソッドは、副作用だけを期待して使い捨てるものではありません。業務上意味のある結果を戻り値として返すことも正しい設計です。
出庫処理のように保存、帳票出力、配車処理など複数の処理が関係する場合は、ドメインモデルにすべてを詰め込まず、戻り値、結果オブジェクト、ドメインイベントなどを状況に応じて選択します。
DDDの本質は特定の実装パターンを守ることではなく、業務知識を適切な場所に配置し、変更しやすいソフトウェアを作ることにあります。


コメント