3

私は現在、複数のデータソースを使用して必要なデータを消費するシステムを設計中です。以下に示す概念をモデル化しようとしています(画像を投稿しますが、十分なポイントがありません!)。そこでは、顧客が多くの製品と関連付けることができます。顧客は「顧客サブシステム」に保存され、製品と顧客製品は「製品サブシステム」に保存されます。

public class Customer
{
    public string FirstName { get; set; }

    public Guid ID { get; set; }
}
public class CustomerProduct
{
    public Guid ID { get; set; }

    public Customer Customer { get; set; }

    public Product Product { get; set; }
}
public class Product
{
    public string Name { get; set; }

    public double Price { get; set; }

    public Guid ID { get; set; }
}

「顧客」エンティティは、Webサービスを介してアクセスする必要があるシステムに物理的に永続化されます。「ConsumerProduct」および「Product」エンティティは、NHibernateをORMとして使用して、SQLデータベースに永続化されます。

設計の一環として、リポジトリを使用して、ドメインモデルからデータ永続化テクノロジを抽象化することを計画していました。したがって、ICustomerRepository、ICustomerProductRepository、IProductRepositoryの3つのリポジトリインターフェイスがあります。次に、CustomerProductおよびProductリポジトリ用の具体的なNHibernate実装と、Customerリポジトリ用の具体的なWebサービスアクセス実装を作成します。

私が苦労しているのは、さまざまなサブシステムで永続化されているエンティティがどのように相互作用するかです。理想的には、CustomerProductエンティティがCustomerオブジェクトを返す物理的な「Customer」プロパティを持つリッチドメインモデルが必要です。ただし、顧客エンティティには別のデータストアからアクセスする必要があるため、これがどのように機能するかわかりません。

この問題を解決するために私が見ることができる唯一の方法は、CustomerProductエンティティで顧客への完全な参照を維持せず、代わりに参照を保持することです。その後、顧客への参照を取得する必要があるたびに、顧客を経由します。リポジトリ。

この問題を解決する方法について誰かが提案できる提案をいただければ幸いです。

4

1 に答える 1

3

こんにちは私は以前あなたの状況にあったことはありませんが、他のサブシステムと通信するドメインを設計しています。全体像はわかりませんが、顧客エンティティは他のCustomerProductおよびProductからより分離されているようです。では、モデルを共通のGUIで表示するのは正しいと思いますが、分離されているのはデータソースだけですか?

まず、さまざまな方法でこれを解決できます。また、メンテナンス、稼働時間、サポートなどの非機能要件についても自問する必要があります。両方のシステムが常に同時に稼働しているのでしょうか、それともシステムがダウンしているのでしょうか。私が探している手がかりは、サブシステムと同期または非同期(メッセージキュー)を通信する必要があるかどうかです。これは、NServiceBusを使用して実現できます。

ただし、ドメインに焦点を合わせるには、ドメインにモデルが1つしかないように見せることをお勧めします。これは、さまざまな方法で実行できます。

1)ICustomerRepository(オブジェクトのコレクションに対して機能しているように機能するインターフェイスコントラクト)を、サブシステムでWebサービスを使用するインフラストラクチャ関連のリポジトリによって実装します。ヒントは、キーの競合が発生するように、キーとしてGUIDを使用する必要があるということです。このアプローチでは、他のエンティティからの顧客との関係/関連付けはできません。それらはリポジトリを介してのみ行われます(これは、ジミー・ニルソンが彼の本(http://jimmynilsson.com/blog/)で使用するソリューションであり、多くの双方向の関係でモデルを強化しません)。

2)ユースケースがモデルをターゲット/使用する方法によって異なりますが、1つの物理的な場所に存在し、CustomerServiceとCustomerProcuctServiceおよびProductServiceを使用するアプリケーション全体のサービスレイヤーを作成できます。ドメインロジックがアプリケーション層にリークするのを防ぐために、これらのエンティティ間の調整の一部を、異なるサービス間でいくつかのイベントを調整するドメインイベントハンドラーにカプセル化できます。

3)他のサブシステムCustomerGUIDをキーとして持つCustomerAdapterクラスを作成することもできます(Customer Webサービスがキーを制御しているため、キーを生成できません)。ただし、Nhibernateでマップして、CustomerProductとCustomerAdapterの間に関係を持たせることができます。ただし、CustomerAdapterをマップする場合は、GUIDのみをロードします。次に、Spring.Net Windsorまたはその他のDIツールを使用して、ICustomerAdapterServiceがプロパティに挿入されることを確認します。次に、NhibernateのcustomerAdapterのプロパティ(customername、addressなど)をマップしないようにします。ただし、CustomerAdapterからAdressを取得/読み取ると、ICustomerAdapterServiceから取得し、他のすべての値も設定します。これは、ドメインモデルにサービスがないなど、一部のDDDルールに違反するため、推奨されるソリューションではありません。しかし、この観点から見ると、次のようになります。分散ドメイン内の問題を解決するため、実際にはドメインサービスと見なすことができます。ただし、WCFサービスの実装などのインフラストラクチャ関連のものが含まれているため、サービスの実装を別のインフラストラクチャレイヤー/アセンブリに含める必要があります

最も簡単なのはソリューション2です。顧客エンティティがアプリケーション層のサービスによってのみアクセスされるという事実を処理できる場合。ただし、このアプリケーションサービスレイヤーは、2つのサブシステム間の優れた破損防止レイヤーになる可能性があります。今日、2つのサブシステムがあるのにはおそらく理由があります。ただし、インタラクションフローの例(ドメインがどのようになっているかについての詳細な知識はありません):

  • GUIはアプリケーションサービスCustomerProductServiceメソッドBuyNewProduct(CustomerDTO customer、ProductDTO newProduct)を呼び出します
  • CustomerProductServiceには、ICustomerProductRepositoryとIProductRepositoryがコンストラクターに挿入されています。また、プロパティCustomerFacadeServiceに注入されるインフラストラクチャサービスICustomerFacadeService(名前を今すぐ変更:-))もあります。このサービスの作成は、Create()とCreateExtendendedWithCustomerService()の2つの作成メソッドを持つファクトリによって行われます。後者もCustomerServiceFacadeを注入します
  • メソッドBuyNewProduct(...)は、CustomerDTOをアセンブルし、CustomerGUIDを使用して、他のサブシステムのWebサービスを呼び出すCustomerFacadeServiceからCustomerをロードします。
  • ロードされた顧客はそれが実際に存在することを確認しますが、今度はIProductRepositoryを使用して製品をロードします
  • CustomerGUID値とProductEntityの両方を使用して、新しいCustomerProductエンティティ(実際にはProductsとCustomer GUIDの間の単なるマッピングクラス)を作成し、ICustomerProductRepositoryを介して保存します。
  • これで、別のインフラストラクチャサービスを呼び出して、新製品にアクセスできることが通知される電子メールを顧客に送信できます。または、この通知をctorに注入されたIEmailServiceを持つイベントハンドラー(アプリケーションサービスレイヤー内)に委任するドメインイベントをCustomerProductエンティティに作成できます。次に、新しい顧客を製品に接続するときに通知を送信するというドメイン知識を習得しました。

これが、より少ない苦痛でドメインをモデル化するのに役立つことを願っています。DDDを行うのは苦痛だからです。同僚、ドメインの専門家、そして鏡の前で自分自身と多くの議論が必要です:)これは正しい道ですか?DDDsample.netでドメインイベントを探すか、UdiDahanとドメインイベントを検索してください。


私はここに答えを書きます、より多くのスペース:

インタラクションフローの例でCustomerFacadeServiceとも呼ばれるCustomerAdadpterについては、私の意見です。実装方法はアプリケーションによって異なります。ほとんどのユーザーケースは、メインシステムを呼び出して「クラウドサブシステム」を呼び出します。これにより、稼働時間が長くなります。-次に、キューは不要で、クラウドにWCFサービスがあります。CustomerFacadeServiceは、アプリケーション層が必要とするメソッドを公開し、必要なすべてのDTOオブジェクトをアセンブルするサービスラッパーになります。クラウドシステムがメインシステムにもコールバックする場合は、いくつかのメソッドをサービスとして公開する必要があります。次に、NServiceBusエンドポイントをWCFサービスとして公開するオプションがあります。これにより、情報を失うことなくメインシステムを停止することができます。しかし、常にたくさんの尻があります... もちろん、インフラ技術者が修正プログラムをインストールしたり、メインシステムのWebサーバーを再起動したりする場合は、別のマシンにWCFサービスをインストールする必要があります。メインシステムがダウンしているときにクライアントが応答を待機している場合、クライアントはどのくらい待機しますか?それほど長くはないと思います。したがって、これの利点を理解できるシナリオの1つは、実行する必要のあるバッチ/レポートがあり、システムの一部がダウンしている場合、レポートが再びアップするとレポートが続行されることです。

これは、WCFサービスとして公開されているNServiceBusの例です。しかし、私はそれを正確に行った経験はなく、「それができる」という知識だけがあります。 http://docs.particular.net/nservicebus/architecture/nservicebus-and-wcf

于 2011-04-07T11:47:21.213 に答える