web-dev-qa-db-ja.com

トランザクション性はDDDアプリケーションにどのように実装されますか?

私は最近DDDについて検索して読んでいますが、これまでのところ、DDDの資金は理解できたと思います。

私がよく理解していれば、アーキテクチャは次のようになります。

Database <--SQL--> DAO/ORM <--CRUD--> Repository/Aggreagtes <--Business--> **¿?** <-- Controller --> Internet/Client/UI

私の疑問は¿?ギャップを一変させることです。私は通常それをサービスで満たします。

多くの場合、私のサービスはAnemic Domain Modelの最初の証拠です。これは、すべてのビジネスロジックがこれらのサービスにあるためです(それらの実装は非常に手続き型です)。結果として、私のドメインモデルはPOJOの単なるセットです。

私の意図は、現在のプロジェクトを徐々に、よりリッチなドメインモデルとより薄いサービスレイヤーに移行することです。ただし、トランザクション性とそれが属するレイヤーについて懸念しています。

上記のgapを埋める方法について検索すると、これが見つかりました question

リンクとチェック済みの回答をたどると、私は次のことを前提としています:

  • DDDにはまだサービスがあります。これらのサービスは、リポジトリー(および集約ルート)を介してビジネス操作を実行します。

  • サービスは、集約ルートやリポジトリではカバーできないビジネスニーズをカバーすることを目的としています。

  • サービスは、UnitOfWork(UoW)コンポーネントを介してビジネストランザクションを実行します。 UoWには、1つ以上の集約されたルートとリポジトリが含まれる場合があります。

質問:これは、DDDでビジネスレイヤーとトランザクション性を実装する方法ですか?(App Service-> UoW->リポジトリ)

もし、そうなら

[ボーナス質問]:アプリケーションイベントとハンドラーがこのようなアーキテクチャにどのように適合するか?サービスはハンドラーに変換されていますか?(ハンドラー-> UoW->リポジトリ)?

私はどんな種類の入力にも感謝しています。 dddレイヤーの結合方法や、可能な限り少ない結合でそれらを結合する方法に少し戸惑っています。

8
Laiv

UoWには、1つ以上の集約されたルートとリポジトリが含まれる場合があります。

いいえ、絶対に違います。それは全体のポイントを逃しています。常に一度に1つの集計を変更します(トランザクションごとに1つ)。

トランザクションは通常、アプリケーションコンポーネントと永続性コンポーネントの間の調整です。アプリケーションはトランザクションを開始し(必要に応じてUoW)、ターゲットアグリゲートを読み取り、アグリゲートを変更して保存し、コミットします。

そのコミットが成功した場合、そのアグリゲートへの書き込みの競合はなく、コマンド自体は成功しています。書き込みが競合している場合、コミットは失敗し、アプリケーションコンポーネントは回復戦略(マージ、新しい開始点からのコマンドの再実行、呼び出し元への失敗の報告など)を把握します。

1つのトランザクションで2つのアグリゲートを変更する必要がある場合、アグリゲートルートの設計が悪いことが原因である可能性があります。

それ、またはビジネスの実際の要件を理解するための失敗。実際のビジネスケースの柔軟性が非常に高い場合、2つの変更を密結合する必要があると想定するのは比較的一般的なパターンです。古典的な例:実際​​に企業が当座貸越のペナルティを喜んで発生させるときに、口座残高がゼロを下回ってはならないという仮定。

13
VoiceOfUnreason

集計内のデータを処理するだけでは、すべての不変条件が満たされるわけではありません。操作をバンドルするために、少なくとも同じ制限付きコンテキスト内で、サービスレベルのトランザクションが必要になる場合があることをお勧めします。

この例として、口座間での送金があります。 1つのトランザクションが成功し、もう1つのトランザクションが失敗した場合、問題が発生します。代替策は、ロジックを本当に複雑にするようなワークフロー/状態制御の方法を実装することです。リッチドメインモデルの目的を打ち負かしたと私は主張します。

0
user2813490