29

背景: 私自身の明快さ/自己教育のために、TDD + DDD を使用して単純な注文入力アプリケーションを実装しようとしています。私の主な目標は、関心を分離することによってアーキテクチャをクリーンに保つことです。

私は(今のところ)4つのレイヤーを持っています...

  1. 「集約ルート」で GetById、保存、操作を実行できる CustomerRepository クラスを使用した持続性/DAL、Customer およびそれに関連する Orders および OrderItems。「貧乏人の依存性注入」を可能にするために

  2. 注文サイズと顧客の場所に基づいて税金、割引、配送ロジックを適用し、新しい注文を作成するのに役立つきめ細かい操作を実行する「ビジネス エンティティ」クラスを含むドメイン/BLL レイヤー。

  3. アプリケーション ファサード (アプリ サービス / オーケストレーション) には、「ビジネス エンティティ」をオーケストレーションし、プレゼンテーション (および場合によっては Web サービス レイヤー) とのおしゃべりを減らすための分厚い粗いクラスが含まれています。

  4. プレゼンテーション層

さらに、重要なレイヤー間で POCO DTO を渡したいと考えています。特に、Persistence=>Domain レイヤーと ApplicationFacade=>Presentation レイヤーの間です。したがって、共有パッケージで定義された適切な関係を持つ CustomerDto、OrderDto、OrderItemDto があります。

コンストラクター インジェクションを使用して ICustomerRepository の実装を Customer の "ビジネス エンティティ" クラスに挿入し、"ビジネス エンティティ" で Customer.Save() を呼び出して作成/更新プロセスを開始し、最終的に Save メソッドを呼び出します。顧客リポジトリ。結局のところ、Customer は「集約ルート」であり、保存するために必要なすべての情報を持っています...また、注入された CustomerRepository の「キーパー」でもあります。

問題: ここで問題が発生しました。Domain/BLL Layer をできるだけ純粋に保ち、サードパーティのフレームワークや API との結合を避けたいのです、Customer.Save() メソッドは、Customer の「集約ルート」とそのすべての Orders および OrderItems を次のように変換する必要があります。注入された Persistence レイヤー CustomerRepository に転送するための DTO バージョン ... そしてそれは Automapper の仕事です。

問題は... Automapper を Domain/BLL レイヤーに配置しないと、どこに配置すればよいかよくわかりませ

仕事はオーケストレーションですが、それを ApplicationFacade に入れるのは適切ではありません。

これをドメイン/BLL レイヤーに配置するのは適切ではありません。

したがって、私は何かを見逃しているように感じます...このタスクを完了するためにすべての作業部分がどのように連携する必要があるかについて、根本的な誤解を持ってこれに取り組んでいます. 助言がありますか?(優しくしてください。私はこれに慣れておらず、SOも初めてです。これまでに持っているもののコードを表示する必要がある場合はお知らせください。)

4

1 に答える 1

52

あなたの特定の質問に答えるために、私はあなたのアーキテクチャについてより一般的に話します。プロジェクト用に考案したアーキテクチャは、DDDで使用される一般的なアーキテクチャとは微妙に異なります。責任を分割する方法は一般的ですが、DDDでは、ドメインクラスはそれ自体の永続性に責任を負いません。実際、DDDのマントラは永続性の無知です。これは基本的に、ドメインクラスが永続性に依存しないことを意味します-それらにはSaveメソッドがありません。代わりに、アプリケーションサービス(アーキテクチャ内のアプリケーションファサードレイヤー)は、リポジトリと連携してドメインエンティティを再構成および永続化します。

次に、リポジトリを実装する場合、通常、基盤となる永続化テクノロジとドメインクラスの間に明示的なDTOは必要ありません。NHibernateやEFなどのORMでは、ドメインクラスとリレーショナルテーブル間のマッピングは、マッピングクラスまたはXMLベースの構成のいずれかで表現されます。その結果、ドメインクラスは暗黙的にマッピングされます。DTOは必要ありません。DTOが必要な場合もあります。その場合、DTOとドメインクラス間のマッピングは、リポジトリの実装によってカプセル化する必要があります。これは、AutoMapperを呼び出すことができる1つの場所です。

最後に、プレゼンテーション層とアプリケーション/ドメイン層の間でDTOを使用して通信するのが一般的な方法です。マッピングを実行する場所を正確に決定するには、プロジェクトに最適なアーキテクチャを深く掘り下げる必要があります。最新のDDDアーキテクチャのほとんどは、ヘキサゴナルアーキテクチャに基づいています。六角形のアーキテクチャでは、ドメインが中心にあり、他のすべての「レイヤー」がドメインを特定のテクノロジーに適合させます。たとえば、リポジトリはアダプタと見なすことができますドメインと特定のデータベーステクノロジーの間。ASP.NET WebAPIは、ドメインとHTTP/RESTの間のアダプターと見なすことができます。同様に、プレゼンテーション層は、ドメインと特定の間のアダプターと見なすことができます。DTOは、これらの各アダプター内に現れる可能性があり、これらのDTOとの間でマップするのはアダプターの責任です。

典型的な例は、アプリケーションサービスを使用して、ドメイン上にファサードを確立することです。まだDTOは使用されていません。次に、ASP.NET WebAPI(アダプター)を使用してサービスレイヤー(DDDでホストサービスを開く)を作成します。ASP.NET WebAPI固有のDTOを作成し、これらのDTOとの間でマップするのはこのアダプター次第です。したがって、AutoMapperを使用する場合は、このレイヤーで呼び出す必要があります。これは、明示的に、またはアクションフィルターを使用してアスペクト指向の方法で実行できます。同じことがプレゼンテーション層にも当てはまります。プレゼンテーション層は、アプリケーションサービス、またはASP.NETWebAPIオープンホストサービスに直接結合できます。いずれの場合も、ドメインクラス(アプリケーションサービスから、またはWebAPIからのDTOから)とViewModelなどの独自のプリミティブの間でマッピングするのはプレゼンテーション層の責任です。

于 2012-12-08T21:12:51.130 に答える