DDD-多数の子を持つ集合ルート


10

私はこの質問の前置きとして、私はDDDに比較的慣れていないので、ここでいくつかの根本的な間違いを犯しているかもしれないと言います。

私は、(財務的な意味で)アカウントとトランザクションの概念を含むプロジェクトに取り組んでいます。アカウントはそれに対して入力された多くのトランザクションを持つことができます。

アカウントとトランザクションは両方ともエンティティであり、アカウントはトランザクションを含む集約ルートであるように見えます。これは、トランザクションがアカウントなしでは存在できないためです。

しかし、これをコードに適用するようになると、すぐに問題が発生しました。多くの場合、アカウントのすべてのトランザクションのリストを常に保持しておくことは、特に役に立ちません。アカウントの残高を計算したり、与信限度などの不変条件を適用したりできることに興味がありますが、トランザクションのサブセットを簡単に操作できるようにしたい(たとえば、日付範囲内のトランザクションを表示したい)。

後者の場合、私が使用していた場合、TransactionRepositoryリスト全体(場合によっては非常に大きい)をロードすることなく、必要なオブジェクトだけに効率的にアクセスできます。ただし、これにより、アカウント以外のものをトランザクションで使用できるようになります。つまり、アカウントの概念を集約ルートとして破っています。

このような状況に人々はどのように対処しますか?集約ルートに対して潜在的に膨大な数の子をロードすることによるメモリとパフォーマンスへの影響を受け入れますか?

回答:


9

「なしでは存在できない」ルールに注意することをお勧めします。これは、UML / OO設計での構成の概念について説明しており、元のDDDブルーブックでアグリゲートを設計するための規定されたアプローチの1つである可能性があります(それについては不明です)が、その後大幅に改訂されました。トランザクション整合性境界の観点から集計を確認することをお勧めします。

一部の不変式は必然的に複数の集合体にまたがるため、集合体のロックと同時実行性の問題が発生するため、指摘するようなパフォーマンスの問題が発生する集約を大きくしすぎたり、小さくしすぎたりしないことを目的としています。

正しい集計サイズは、理想的には、特定のビジネストランザクションで変更するものの輪郭に理想的に一致します。あなたの例では、複数の金融トランザクションにまたがるドメイン不変式が多くない場合はTransaction、それ自体で集計ルートを作成するのが最善の解決策になる可能性があります。


ありがとう、一貫性の境界について読みます。Transactionを独自の集約ルートにするというあなたの提案は良いものになると思います。あなたが言うように、私は複数のトランザクションにまたがる不変条件をあまり持っていません。
krixon 2015

7

tl; dr-必要に応じてルールを破る。DDDはすべての問題を解決できるわけではありません。実際、それが与えるオブジェクトのアイデアは、良いアドバイスと良いスタートですが、いくつかのビジネス上の問題にとっては本当に悪い選択です。物事のやり方のヒントと考えてください。


すべての子(トランザクション)を親(アカウント)でロードする問題について-多くのORMが解決したn + 1の問題(Googleの問題)に遭遇したようです。

子(トランザクション)を遅延ロードすることで解決できます-必要な場合のみ。

しかし、問題を解決するためにTransactionRepositoryを使用できることを言及することで、すでに知っているように聞こえます。

アカウントのみが使用できるようにそのデータを「隠蔽」するには、パブリックリレーショナルテーブルのように、他の人がデータを逆シリアル化する方法がない場所にデータを格納する必要もありません。アカウントの「ドキュメント」とともにドキュメントDBに保存できます。どちらにしても、誰かが十分に頑張ったとしても、データを見ることができます。そして、それで「働く」。そして、あなたが見ていなければ、彼らはそうするでしょう!

したがって、権限を設定することはできますが、その後、「アカウント」を別のプロセスとして実行する必要があります。

ここで実際に気づくのは、DDDとオブジェクトモデルの純粋な使用が、時々あなたを隅に追いやることです。もちろん、DDDの設計原則を活用するために「構成」/集計ルートを使用する必要はありません。これは、制約に適合する状況があるときに使用できる1つの方法にすぎません。

誰かが「早期に最適化しないでください」と言うかもしれません。ただし、この場合は、答えがわかっています。アカウントでそれらをすべて永久に維持する方法を停止するのに十分なトランザクションがあります。

本当の答えは、SOAの立ち上げを始めることです。私の職場では、Udi Dahanの「分散コンピューティング」のビデオを見て、nServiceBusを購入しました(私たちの選択にすぎません)。アカウント用のサービスを作成します-独自のプロセス、メッセージキュー、それだけが参照できる関係データベースへのアクセス、そして...ビオラを使用すると、プログラムでSQLステートメントをハードコーディングし、いくつかのCobolトランザクションスクリプトを投入することもできます(冗談)もちろん)しかし、真剣に考えているのは、最もスマートなOO / Javaスノッブがこれまで夢に見た以上のものです。

とにかくそれをうまくモデリングすることをお勧めします。ここでは、サービスをミニバウンドカウントエクステントとして扱うことで、問題なくアグリゲートルートの利点を得ることができます。

もちろん、これには欠点があります。RPC(Webサービス、SOAP、またはREST)をサービスの内外でそれらの間だけで実行することはできません。あるいは、一時的な結合により「ノット」と呼ばれるSOAアンチパターンを取得します。通信パターンの反転、別名「Pub-Sub」を使用する必要があります。これは、イベントハンドラーやイベントレイザーのように機能しますが、(1)プロセス間(1つのマシンでオーバーロードされている場合は、別のマシンに配置できます)。

実際の問題は、別のサービスからデータを取得して「ブロック」または待機する必要のあるサービスを望まないことです。メッセージを起動して忘れ、プログラム内の別の場所でハンドラーがそれをピックアップして処理を完了する必要があります。つまり、ロジックを異なる方法で実行する必要があります。nServicebusは、「サガ」パターンを自動化してこれの一部を支援しますが、最終的には別のコーディングスタイルを開発する必要があります。あなたはまだそれをすべて行うことができます、単にそれを別の方法で行う必要があります!

Arnon Rotem-Gal-Oz著の本「SOA Patterns」は、これに関する多くの質問に答えます。必要に応じて外部サービスから独自のサービスに定期的にデータを複製する「アクティブサービスパターン」の使用を含みます(多くのRPCが必要か、リンクが信頼できない/公開/購読エコシステムにない)。

プレビューするには、UI をサービスにRPCする必要があります。レポートは、サービスのデータベースから供給されるレポートデータベースから生成されます。一部の人々は、報告は不要であり、問​​題は別の方法で解決されるべきであると言います。その話に懐疑的です。

しかし結局のところ、すべてを適切に1つのサービスに分類できるわけではありません。世界はラビオリのコードでは動かない!したがって、ルールを破る必要があります。必要がない場合でも、プロジェクトの新しい開発者は、プロジェクトを離れたときにそれを行います。しかし、心配しないでください。できる限りのことをすると、規則に従う85%によって、プログラムの保守性が大幅に向上します。

わあ、それは長かった。


細かい対応に感謝します。SOAについては間違いなくいくつか読んでいきます。
krixon 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.