13

完璧なドメイン モデル設計である実際のシナリオがあります。これは、象限ごとに異なる状態を持つ複数の象限を持つフィールドです。したがって、私の集計ルートはフィールドです。ここで、重要な質問が 1 つあります。永続的な無知なドメイン モデルが必要です。これは理にかなっていると思います。では、リポジトリメソッドの更新をどこで呼び出す必要がありますか? ドメインモデルではありませんよね?では、このオブジェクトの変更追跡プロキシがなく、エンティティでリポジトリを呼び出す必要がない場合、集約ルートの子エンティティをデータベースでどのように更新する必要があるのでしょうか? または、ドメイン モデル パターンを誤解していますか?

私の質問は明確ですか?:)よろしくお願いします最高のラウリン

4

4 に答える 4

13

では、リポジトリ メソッドの更新をどこで呼び出す必要がありますか?

典型的な DDD アーキテクチャでは、通常、リポジトリはアプリケーション サービスによって呼び出されます。アプリケーション サービスは、ドメインをカプセル化するファサードとして機能し、ドメイン オブジェクト、リポジトリ、およびその他のサービスを調整することによってドメインのユース ケースを実装するクラスです。

私はあなたのドメインに精通していませんが、あるものStateから別のものへと移行するユースケースがあるとします。おっしゃるとおりARです。したがって、 a を参照する必要があります:QuadrantFieldFieldFieldApplicationServiceFieldRepository

public class FieldApplicationService
{
    readonly FieldRepository fieldRepository;    

    public void ShiftFieldState(int fieldId, string quadrant, string state)
    {
          // retrieve the Field AR
          var field = this.fieldRepository.Get(fieldId);
          if (field == null)
              throw new Exception();

          // invoke behavior on the Field AR.
          field.ShiftState(quadrant, state);

          // commit changes.
          this.fieldRepository.Update(field);
    }
}

アプリケーション サービス自体は非常に薄いです。ドメイン ロジックは実装しません。リポジトリへのアクセスを含むドメインロジックの実行のためのステージを調整して設定するだけです。プレゼンテーション層やサービスなど、ドメインに依存するすべてのコードは、このアプリケーション サービスを通じてドメイン機能を呼び出します。

リポジトリは、さまざまな方法で実装できます。NHibernate などの ORM を使用することができます。この場合、変更追跡が組み込まれており、通常のアプローチは、明示的な更新を呼び出す代わりにすべての変更をコミットすることです。NHibernate は作業単位を提供するだけでなく、複数のエンティティへの変更を 1 つとしてコミットできるようにします。

あなたの場合、あなたが述べたように、変更追跡がないため、更新の明示的な呼び出しが必要であり、これを処理するのはリポジトリの実装次第です。データベースとして SQL Server を使用している場合、リポジトリのメソッドは、必要に応じてテーブルを更新するストアド プロシージャにUpdateすべてのプロパティを送信するだけです。Field

于 2013-01-10T17:36:37.403 に答える
6

「アプリケーションコード」はリポジトリを呼び出す必要があります。アプリケーション コードがどのようにホストされるかは、インフラストラクチャの問題です。アプリケーション コードをホストする方法の例としては、WCF サービス、Winforms/WPF アプリケーション、または Web サーバーがあります。

リポジトリの実装は、集約ルートとその子エンティティへの変更を追跡し、それらをデータベースに保存する役割を果たします。

次に例を示します。

ドメイン プロジェクト

public DomainObject : AggregateRootBase //Implements IAggregateRoot
{
    public void DoSomething() { }
}

public IDomainObjectRepository : IRepository<DomainObject>, IEnumerable
{
    DomainObject this[object id] { get; set; }
    void Add(DomainObject do);
    void Remove(DomainObject do);
    int IndexOf(DomainObject do);
    object IDof(DomainObject do);
    IEnumerator<DomainObject> GetEnumerator();
}

実施プロジェクト

public SqlDomainObjectRepository : List<DomainObjectDataModel>, IDomainObjectRepository
{
    //TODO: Implement all of the members for IDomainObjectRepository
}

応用プロジェクト

public class MyApp
{
    IDomainObjectRepository repository = //TODO: Initialize a concrete SqlDomainObjectRepository that loads what we need.
    DomainObject do = repository[0]; //Get the one (or set) that we're working with.
    do.DoSomething(); //Call some business logic that changes the state of the aggregate root.
    repository[repository.IDof(do)] = do; //Save the domain object with all changes back to the db.
}

複数の集約ルートへの変更をトランザクション化する必要がある場合は、変更がすべてか無かで行われるようにする必要がある場合は、Unit of Work パターンを検討する必要があります。

これが物事を明確にするのに役立つことを願っています!

于 2013-01-10T16:57:10.463 に答える
6

Aggregate Root (AR) はどこかで更新されます。メッセージ ドリブン アーキテクチャを使用すると、どこかがコマンド ハンドラーになりますが、一般的な目的ではそれがサービスであるとしましょう。このサービスは、リポジトリから AR を取得し、関連するメソッドを呼び出してから、AR をリポジトリに保存します。

AR はリポジトリについて認識していません。AR の関心事ではありません。その後、リポジトリはすべての AR 変更を作業単位として保存します (つまり、すべてかゼロか)。Repo がそれをどのように行うかは、永続化戦略をどのように決定したかによって異なります。

イベント ソーシングを使用している場合、AR はイベントを生成し、Repo はそれらのイベントを使用して AR 状態を保持します。より一般的なアプローチを取る場合、その AR にはおそらくプロパティとして公開された状態データが必要です。メメントパターンといいます。リポジトリは、そのデータを 1 回のコミットで保持します。

しかし、1 つ確かなことは、Domain オブジェクトを扱うときは、持続性の詳細について決して考えてはならないということです。つまり、ドメインを ORM やデータベース固有のものに結合しないでください。

于 2013-01-10T13:26:08.090 に答える
4

私の解決策は、集約ルートがいくつかのイベントを外部のイベントハンドラーに発生させることです。これらのイベントハンドラーは、リポジトリを呼び出してデータベースを更新します。イベントを登録してディスパッチするには、ServiceBusも必要です。私の例を参照してください:

public class Field: AggregateRoot
{
    public UpdateField()
    {
         // do some business
         // and trigger FieldUpdatedEvent with necessary parameters
         ....
         // you can update some quadrants
         // and trigger QuadrantsUpdatedEvent with necessary parameters
    }
}

public class FieldEventHandlers: EventHandler 
{
    void Handle (FieldUpdatedEvent e)
    {
         repository.Update(e.Field);
    }
}

public class QuadrantEventHandlers: EventHandler 
{
    void Handle (QuadrantsUpdatedEvent e)
    {
         repository.Update(e.Quadrant);
    }
}
于 2013-01-10T12:54:23.090 に答える