1

ドメインモデルを使用しようとするアプリケーションに取り組んでいます。アイデアは、ビジネス ロジックをドメイン モデルのオブジェクト内に保持することです。現在、オブジェクトが関連オブジェクトをサブスクライブして、それらの変更に反応することで、多くのことが行われています。これは、PropertyChanged および CollectionChanged によって行われます。これは、次の場合を除いて問題ありません。

複雑なアクション : 多くの変更をグループとして処理する必要がある場合 (個々のプロパティ/コレクションの変更ではありません)。トランザクションを「構築」する必要がありますか / どのようにすればよいですか?

永続性: 永続性のために NHibernate を使用します。これは、クラスのパブリック プロパティ セッターも使用します。NHibernate がプロパティにアクセスすると、多くのビジネス ロジックが実行されます (これは不要に思えます)。NHibernate にカスタム セッターを使用する必要がありますか?

全体として、ドメイン モデルにすべてのロジックをプッシュすると、ドメイン モデルがかなり複雑になるようです。何か案は???

これが「サンプル」の問題です(私が使用している安っぽいツールで申し訳ありません):

ここに画像の説明を入力

Project my コンテナとその下のオブジェクトがサブスクライブすることで相互に反応していることがわかります。現在、ネットワークへの変更は NetworkEditor を介して行われますが、このエディターは NetworkData の知識がありません。このデータは、場合によっては別のアセンブリで定義されることもあります。フローは、user->NetworkEditor->Network->NetworkData および関連する他のすべてのオブジェクトから進みます。これはスケールしないようです。

4

1 に答える 1

2

DDD と PropertyChanged/ColactionChanged イベントの組み合わせが最善のアイデアになるのではないかと心配しています。問題は、これらのイベントに基づいてロジックを作成すると、1 つの PropertyChanged が別の PropertyChanged につながり、すぐに制御を失うため、複雑さを管理するのが非常に困難になることです。

ProportyChanged イベントと DDD が完全に適合しないもう 1 つの理由は、DDD ではすべてのビジネス オペレーションを可能な限り明示的に行う必要があるためです。DDD は技術的なものをビジネスの世界に持ち込むものであり、その逆ではないことに注意してください。また、PropertyChanged/CollectionChanged に基づくことはあまり明示的ではないようです。

DDD の主な目標は、集約内の一貫性を維持することです。つまり、集約を呼び出す操作が有効で一貫性があるように、集約をモデル化する必要があります (もちろん、操作が成功した場合)。

モデルを正しく構築すれば、「構築」トランザクションについて心配する必要はありません。集計に対する操作は、トランザクション自体である必要があります。

あなたのモデルがどのように見えるかはわかりませんが、PropertyChanged イベントに依存する代わりに、責任を集約ツリーの 1 レベル「上」に移動し、プロセスに追加の論理エンティティを追加することを検討するかもしれません。

例:

ステータスを持つ支払いのコレクションがあり、支払いが変更されるたびに、顧客注文の合計残高を再計算したいとします。支払いコレクションへの変更をサブスクライブし、コレクションが変更されたときに顧客でメソッドを呼び出す代わりに、次のようにすることができます。

    public class CustomerOrder
    {
        public List<Payment> Payments { get; }
        public Balance BalanceForOrder { get; }

        public void SetPaymentAsReceived(Guid paymentId)
        {
            Payments.First(p => p.PaymentId == paymentId).Status = PaymentStatus.Received;
            RecalculateBalance();
        }
    }

お気づきかもしれませんが、お客様全体の残高ではなく、単一の注文の残高を再計算します。ほとんどの場合、顧客は別の集計に属しており、必要に応じてその残高を照会するだけで問題ありません。これは、まさにこの「集計内のみの一貫性」を示す部分です。この時点では、他の集計は気にせず、単一の注文のみを処理します。それが要件に合わない場合、ドメインは正しくモデル化されていません。

私が言いたいのは、DDD では、すべてのシナリオに適した単一のモデルは存在しないということです。成功するには、ビジネスがどのように機能するかを理解する必要があります。

上記の例を見ると、トランザクションを「ビルド」する必要がないことがわかります。トランザクション全体がSetPaymentAsReceivedメソッド内にあります。ほとんどの場合、1 つのユーザー アクションは、集計を伴うエンティティの 1 つの特定のメソッドにつながる必要があります。このメソッドは、ビジネス オペレーションに明示的に関連しています (もちろん、このメソッドは他のメソッドを呼び出すこともできます)。

DDD のイベントにはドメイン イベントという概念がありますが、PropertyChanged/CollectionChanged の技術イベントとは直接関係ありません。ドメイン イベントは、集計によって完了したビジネス オペレーション (トランザクション) を示します。

全体として、ドメイン モデルのすべてのロジックをプッシュすると、ドメイン モデルがかなり複雑になるようです。

もちろん、複雑なビジネス ロジックを使用するシナリオで使用されることになっているためです。ただし、ドメインが正しくモデル化されていれば、この複雑さを簡単に管理および制御できます。これが DDD の利点の 1 つです。

例を提供した後に追加:

では、Project という名前の集約ルートを作成するのはどうでしょうか。Repository から集約ルートを構築する場合、NetworkData で埋めることができ、操作は次のようになります。

    public class Project
    {
        protected List<Network> networks;
        protected List<NetworkData> networkDatas;

        public void Mutate(string someKindOfNetworkId, object someParam)
        {
            var network = networks.First(n => n.Id == someKindOfNetworkId);
            var someResult = network.DoSomething(someParam);

            networkDatas.Where(d => d.NetworkId == someKindOfNetworkId)
                .ToList()
                .ForEach(d => d.DoSomething(someResult, someParam));
        }
    }

NetworkEditor は、NetworkId を使用する Project を通じてではなく、Network 上で直接動作しません。

于 2011-08-10T13:56:40.953 に答える