誰かがいくつかの例を提供することで、ドメインとアプリケーションサービスの違いを説明できますか?また、サービスがドメインサービスである場合、このサービスの実際の実装をドメインアセンブリ内に配置しますか?その場合、リポジトリをそのドメインサービスに挿入しますか?いくつかの情報は本当に役立ちます。
サービスには、3つのフレーバーがあります:ドメインサービス、アプリケーションサービス、およびインフラストラクチャサービス。
ドメインオブジェクトと共にドメインサービスを維持することは賢明です。それらはすべてドメインロジックに焦点を当てています。はい、リポジトリをサービスに挿入できます。
通常、アプリケーションサービスは両方のドメインサービスを使用しますandリポジトリは外部リクエストを処理します。
お役に立てば幸いです!
(読みたくない場合は、下部に要約があります:-)
私も、アプリケーションサービスの正確な定義に苦労しています。 Vijayの答えは1か月前の私の思考プロセスに非常に役立ちましたが、その一部に反対するようになりました。
アプリケーションサービスに関する情報はほとんどありません。集約ルート、リポジトリ、ドメインサービスなどのテーマについては広範囲に説明しますが、アプリケーションサービスについては簡単に説明するか、完全に省略します。
MSDN Magazineの記事 ドメイン駆動設計入門 は、ドメインモデルを変換および/または外部クライアントに公開する方法としてのアプリケーションサービスについて説明しています。 WCFサービスとして。これが、Vijayがアプリケーションサービスについて説明する方法です。この観点から、アプリケーションサービスはドメインへのインターフェースです。
オニオンアーキテクチャに関するジェフリーパレルモの記事(パート one 、 two 、および three )を読んでください。彼は、ユーザーのセッションなど、アプリケーションサービスをアプリケーションレベルの概念として扱います。これはアプリケーションサービスに対する私の理解に近いものですが、このテーマに関する私の考えとはまだ一致していません。
私はアプリケーションサービスをアプリケーションによって提供される依存関係と考えるようになりました。この場合、アプリケーションはデスクトップアプリケーションまたはWCFサービスである可能性があります。
例の時間。ドメインから始めます。ここには、外部リソースに依存しないすべてのエンティティとドメインサービスが実装されています。外部リソースに依存するドメインの概念は、インターフェースによって定義されます。可能なソリューションレイアウトは次のとおりです(プロジェクト名は太字):
私のソリューション - My.Product.Core (My.Product.dll) -DomainServices IExchangeRateService Product ProductFactory IProductRepository
Product
およびProductFactory
クラスは、コアアセンブリに実装されています。 IProductRepository
は、おそらくデータベースによってサポートされているものです。これの実装はドメインの関心事ではないため、インターフェイスによって定義されます。
ここでは、IExchangeRateService
に焦点を当てます。このサービスのビジネスロジックは、外部Webサービスによって実装されます。ただし、その概念は依然としてドメインの一部であり、このインターフェイスで表されます。
外部依存関係の実装は、アプリケーションのインフラストラクチャの一部です。
マイソリューション + My.Product.Core (My.Product.dll) - My.Product.Infrastructure (My.Product.Infrastructure.dll) -DomainServices XEExchangeRateService SqlServerProductRepository
XEExchangeRateService
は、 xe.com と通信することにより、IExchangeRateService
ドメインサービスを実装します。この実装は、インフラストラクチャアセンブリを含めることにより、ドメインモデルを利用するアプリケーションで使用できます。
アプリケーションサービスについてはまだ言及していないことに注意してください。それらを今から見ていきましょう。迅速な検索にキャッシュを使用するIExchangeRateService
実装を提供したいとしましょう。このデコレータクラスの概要は次のようになります。
public class CachingExchangeRateService : IExchangeRateService
{
private IExchangeRateService service;
private ICache cache;
public CachingExchangeRateService(IExchangeRateService service, ICache cache)
{
this.service = service;
this.cache = cache;
}
// Implementation that utilizes the provided service and cache.
}
ICache
パラメーターに注目してください。この概念はドメインの一部ではないため、ドメインサービスではありません。それはアプリケーションサービスです。これは、アプリケーションによって提供されるインフラストラクチャの依存関係です。これを実証するアプリケーションを紹介しましょう。
私のソリューション - My.Product.Core (My.Product.dll) -DomainServices IExchangeRateService Product ProductFactory IProductRepository - My.Product.Infrastructure (My.Product.Infrastructure.dll) -ApplicationServices ICache -DomainServices CachingExchangeRateService XEExchangeRateService SqlServerProductRepository - My.Product.WcfService (My.Product.WcfService.dll) -ApplicationServices MemcachedCache IMyWcfService.cs + MyWcfService.svc + Web.config
これらはすべて、次のようにアプリケーションにまとめられます。
// Set up all the dependencies and register them in the IoC container.
var service = new XEExchangeRateService();
var cache = new MemcachedCache();
var cachingService = new CachingExchangeRateService(service, cache);
ServiceLocator.For<IExchangeRateService>().Use(cachingService);
完全なアプリケーションは、3つの主要な層で構成されます。
ドメイン層には、ドメインエンティティとスタンドアロンドメインサービスが含まれます。外部リソースに依存するすべてのドメインコンセプト(これにはドメインサービスだけでなくリポジトリも含まれます)は、インターフェースによって定義されます。
インフラストラクチャ層には、ドメイン層からのインターフェースの実装が含まれています。これらの実装は、アプリケーションに提供する必要がある新しいnon-domain依存関係を導入する場合があります。これらはアプリケーションサービスであり、インターフェイスによって表されます。
アプリケーション層には、アプリケーションサービスの実装が含まれています。インフラストラクチャ層によって提供される実装が十分でない場合、アプリケーション層にはドメインインターフェイスの追加の実装も含まれる場合があります。
この観点はサービスの一般的なDDD定義と一致しない場合がありますが、ドメインをアプリケーションから分離し、複数のアプリケーション間でドメイン(およびインフラストラクチャ)アセンブリを共有できます。
アプリケーションサービスとドメインサービスの違いを理解するのに役立った最良のリソースは、エリックエバンスの貨物サンプルのJava実装でした here が見つかりました。ダウンロードしない場合、RoutingService(ドメインサービス)とBookingService、CargoInspectionService(アプリケーションサービス)の内部をチェックアウトできます。
私の 'aha'の瞬間は、2つのことによって引き起こされました。
ドメインサービスは、ユビキタス言語とドメインタイプで表現されます。つまり、メソッドの引数と戻り値は適切なドメインクラスです。
リンゴとオレンジを分離する上で大きな助けとなるのは、アプリケーションワークフローの観点から考えることです。通常、アプリケーションワークフローに関するすべてのロジックは、アプリケーション層に含まれるアプリケーションサービスになりますが、モデルオブジェクトとして適合しないドメインの概念は、1つ以上のドメインサービスを形成します。
Red Book(Implementing Domain Driven Design、Vaughn Vernon著)から、これが概念の理解方法です。
ドメインオブジェクト(エンティティおよび値オブジェクト)(サブ)ドメインに必要な動作をカプセル化し、自然で表現力豊かで理解しやすいものにします。
ドメインサービスsingleドメインオブジェクトに収まらないような動作をカプセル化します。たとえば、Book
をClient
に貸し出している本ライブラリ(対応するInventory
の変更を含む)は、ドメインサービスから行うことができます。
アプリケーションサービスユースケースのフローを処理し、必要な追加の懸念事項を含めます上にドメインの。多くの場合、外部クライアントが使用するために、APIを介してこのようなメソッドを公開します。前の例を基にして、アプリケーションサービスは次のメソッドLendBookToClient(Guid bookGuid, Guid clientGuid)
を公開します。
Client
を取得します。Book
を取得します。Client
およびBook
を渡して)実際のドメインロジッククライアントへの本の貸し出しを処理します。たとえば、本の入手可能性を確認することは、ドメインロジックの一部であることは間違いないと思います。一般に、アプリケーションサービスには非常に単純なフローが必要です。複雑なアプリケーションサービスフローは、多くの場合、ドメインロジックがドメイン外に漏れていることを示しています。
ご覧のとおり、ドメインモデルは非常にcleanのままで、ドメインの専門家と簡単に理解して議論できます。懸念。一方、アプリケーションフローはalsoにより管理がはるかに簡単です。これは、ドメインの懸念が軽減され、簡潔で簡単になるためです。
ドメインサービスはドメインの拡張子です。ドメインのコンテキストでのみ表示されます。これは、たとえばclose accountなどのユーザーアクションではありません。ドメインサービスは、状態がない場合に適合します。それ以外の場合は、ドメインオブジェクトになります。ドメインサービスは、他の共同作業者(ドメインオブジェクトまたは他のサービス)を使用する場合にのみ意味のあることを行います。そして、意味をなすことは、別の層の責任です。
アプリケーションサービスは、ドメインオブジェクトとサービス間の相互作用を初期化および監視するレイヤーです。フローは一般的に次のようになります:リポジトリからドメインオブジェクトを取得し、アクションを実行して、そこに戻す(またはしない)。さらに多くのことができます-たとえば、ドメインオブジェクトが存在するかどうかを確認し、それに応じて例外をスローできます。したがって、ドメインオブジェクトとサービスを操作することで、ユーザーがアプリケーションと対話できるようにします(これはおそらくその名前の由来です)。通常、アプリケーションサービスは、可能なすべてのユースケースを表す必要があります。ドメインについて考える前にできる最善のことは、アプリケーションサービスインターフェイスを作成して、実際に何をしようとしているのかをよりよく理解することです。このような知識があると、ドメインに集中できます。
リポジトリは一般的にドメインサービスに挿入できますが、これはかなりまれなシナリオです。ほとんどの場合、それを行うのはアプリケーション層です。
ドメインサービス:単一のエンティティに実際には適合しないメソッド、またはリポジトリへのアクセスが必要なメソッドは、ドメインサービスに含まれています。ドメインサービス層には、独自のドメインロジックを含めることもでき、エンティティや値オブジェクトと同じくらいドメインモデルの一部です。
アプリケーションサービス:アプリケーションサービスは、ドメインモデルの上にあり、アプリケーションアクティビティを調整する薄い層です。ビジネスロジックが含まれておらず、エンティティの状態を保持していません。ただし、ビジネスワークフロートランザクションの状態は保存できます。アプリケーションサービスを使用して、Request-Replyメッセージングパターンを使用して、ドメインモデルにAPIを提供します。
ミレット、C(2010)。プロフェッショナルなASP.NETデザインパターン。ワイリー出版。 92。
ドメインサービス:集約ルートの一部ではないビジネスロジックを表現するサービス。
2つの集計があります:
Product
には名前と価格が含まれます。Purchase
には、購入日、その時点での数量と製品価格で注文された製品のリスト、および支払い方法が含まれます。Checkout
は、これら2つのモデルのいずれの一部でもなく、ビジネスの概念です。
Checkout
は、すべての製品を取得して合計価格を計算し、インフラストラクチャの実装部分で別のドメインサービスPaymentService
を呼び出して合計を支払い、それをPurchase
に変換するドメインサービスとして作成できます。アプリケーションサービス: "orchestrates"またはドメインメソッドを実行するサービス。これは、コントローラーと同じくらい簡単です。
これは通常あなたがする場所です:
public String createProduct(...some attributes) {
if (productRepo.getByName(name) != null) {
throw new Exception();
}
productId = productRepository.nextIdentity();
product = new Product(productId, ...some attributes);
productRepository.save(product);
return productId.value();
// or Product itself
// or just void if you dont care about result
}
public void renameProduct(productId, newName) {
product = productRepo.getById(productId);
product.rename(newName);
productRepo.save(product);
}
ここで、Product
が一意であるかどうかを確認するなどの検証を行うことができます。一意であるProduct
が不変式でない限り、それはUniqueProductChecker
クラスの一部とすることはできず、複数の集合体と対話するため、Product
と呼ばれるドメインサービスの一部である必要があります。
DDDプロジェクトの本格的な例を次に示します。 https://github.com/VaughnVernon/IDDD_Samples
Application Serviceの例といくつかのDomain Serviceの例を見つけることができます