web-dev-qa-db-ja.com

ドメインイベントを使用するか、アプリケーションレイヤーにすべてをオーケストレートさせるかを選択する方法

私はドメインドリブンデザインへの第一歩を踏み出し、ブルーブックとすべてを購入しました。特定のソリューションを実装する3つの方法を見つけました。参考までに、CQRSやイベントソーシングは使用していません。

ユーザーのリクエストがアプリケーションサービスレイヤーに入ってきたとしましょう。その要求のビジネスロジックは、(何らかの理由で)エンティティのメソッドとドメインサービスのメソッドに分けられます。これらのメソッドを呼び出すにはどうすればよいですか?

これまでに収集したオプションは次のとおりです。

  • アプリケーションサービスが両方のメソッドを呼び出すようにする
  • メソッドインジェクション/ダブルディスパッチを使用して、ドメインサービスをエンティティに注入し、エンティティにそれを実行させてから、ドメインサービスのメソッドを呼び出させます(または逆に、ドメインサービスにエンティティのメソッドを呼び出させます)
  • ハンドラーがドメインサービスを呼び出すエンティティメソッドでドメインイベントを発生させます。 (私が話しているドメインイベントの種類は次のとおりです: http://www.udidahan.com/2009/06/14/domain-events-salvation/

これらはすべて実行可能だと思いますが、それらを選択することはできません。私はこれについて長い間考えてきましたが、3つの間のセマンティックの違いが見えなくなるようになりました。何を使用するかについてのガイドラインを知っていますか?

27
dvdvorle

アプリケーションサービスが両方のメソッドを呼び出すようにする

通常、アプリケーションサービスはこのための優れた出発点ですが、常にエンティティにできるだけ近い動作にシフトするようにしてください。アプリケーションサービスはオーケストレーションの役割を果たし、ドメインの動作を実行するためのステージを設定し、そのため必要なすべての依存関係を提供します。ただし、可能な場合は、動作をドメインモデルに委任する必要があります。

メソッドインジェクション/ダブルディスパッチを使用して、ドメインサービスをエンティティに注入し、エンティティにそれを実行させてから、ドメインサービスのメソッドを呼び出させます(または逆に、ドメインサービスにエンティティのメソッドを呼び出させます)

より多くの動作がエンティティまたはドメインサービスに委任されるため、これはより良いアプローチです。これを実装するための最も分離された方法は、エンティティにサービスへの依存関係を表現させることです。これは、目の前の動作を提供するメソッドのパラメーターとしてです。

ハンドラーがドメインサービスを呼び出すエンティティメソッドでドメインイベントを発生させます。

UdiとEvans自身も説明しているように、ドメインイベントパターンは非常に用途が広く、さまざまなシナリオに適用できます。しかし、それに伴ういくつかの合併症があります。まず、ドメインイベントパブリッシャー内に適切なスコープがあることを確認する必要があります。ほとんどの場合、ドメインイベントハンドラーには依存関係があり、IoCコンテナーを使用している場合は、適切なインスタンスが挿入されていることを確認する必要があります。たとえば、Webアプリケーションでは、[ThreadStatic]属性はスコーピングに問題があります。別の複雑さは、転写境界の複雑さです。エンティティがドメインイベントを発生させた後、データベースへのコミットが失敗した場合、すべてのドメインイベントハンドラーがロールバックする方法を必要とするため、トランザクションを考慮する必要があります。それ以外の場合は、無効なイベントを発生させることになります。ただし、これらのベースをカバーしている場合、ドメインイベントはエンティティ自体にドメインロジックをカプセル化するための優れたパターンです。

アプローチ2と3の違いは、ユースケースによって異なります。ドメインイベントは、イベントに応答して追加の動作過去形を呼び出す場合に適用されます。ドメインイベントハンドラーはエンティティの動作に影響を与えることができないため、これは重要な制約です。一方、アプローチ2では、注入されたサービスは特定の動作の依存関係として宣言されているため、動作に影響を与える可能性があります。

20
eulerfx