ドメインサービスの設計方法
最後にドメインサービスの設計方法について紹介します。ドメインサービスの設計ポイントは次の2つです。
- セパレートインターフェイスが必要かどうか検討
- サービスの生成方法を検討
セパレートインターフェイスとは
セパレートインターフェイスとは、マーチン・ファウラー氏が、書籍「エンタープライズ アプリケーション アーキテクチャ(PofEAA:2005年)」にて紹介しているパターンです。
実装クラスとは別のパッケージでインターフェイスを定義することを「セパレートインターフェイス」と呼びます。上図では「IEncryptionService」がインターフェイスで、「MD5EncryptionService」が実装クラスです。このパターンのメリットは、実装クラスもクライアントもインターフェイスに依存するため、依存関係が複雑にならないことです。
セパレートインターフェイスを導入する理由
通常の開発では、システム間の結合度を下げるために、クラスをパッケージ(JavaではJar、.NETではDLL)にまとめて依存関係を管理します。例えば、アプリケーション層のパッケージからドメイン層のパッケージは呼び出し可能ですが、その逆は不可という制約をかけています。しかし、単純な依存関係では管理できない場合があります。
SaaSOvationの例の場合、暗号化サービスに関して、現在はMD5方式による暗号化を行っていますが、今後、別の暗号化方式が採用される可能性があります。このようなときにセパレートインターフェイスを導入して実装クラスを分離するメリットがあります。
実装クラスとセパレートインターフェイスの使い分け
なお、必ずしもセパレートインターフェイスが必要なわけではありません。暗号化サービスのクライアントである認証サービス「AuthenticationService」には、インターフェイスが存在していません。理由としては現時点で複数の実装が存在していないためで、今後実装クラスを差し替える可能性があればセパレートインターフェイスを使えばよいとしています。
サービスの生成方法(セパレートインターフェイスの場合)
セパレートインターフェイスの場合、インターフェイスと実装をひも付ける方法として、大きく分けて次の3つの方法が紹介されています。
- コンスタラクタやメソッドのパラメータを使って、インスタンスを設定する
- オブジェクトを生成する(サービス)ファクトリを使う
- SpringやUnity ContainerなどのIoC/DIコンテナを用いて、サービスのインスタンスを注入する(依存性の注入)
IDDD本ではどれが正解とは明言せず、状況に応じた選択をするとよいとしています。ただし、GitHubのSaaSOvationのサンプルも含めDIコンテナの普及により、最近は3番目の依存性の注入が使われることが多いようです。
最後に
以上、本稿ではDDDのサービスについて紹介し、DDDにおけるサービスの役割、分類、実装ポイントなどを解説しました。ドメインサービスを適切に導入することで、ドメインモデルを適切に表現できることが理解できたと思います。第8回ではDDDの「ドメインイベント」について紹介します。