20

私は ORM を構築しており、各パターンの正確な責任を見つけようとしています。Unit Of Work を使用して 1 つのデータベース トランザクションで更新を管理し、2 つのアカウント間で送金したいとします。次のアプローチは正しいですか?

  1. リポジトリから取得する
  2. それらを自分の作業単位に添付します
  3. ビジネストランザクションとコミットを行いますか?

例:

from = acccountRepository.find(fromAccountId);
to = accountRepository.find(toAccountId);

unitOfWork.attach(from);
unitOfWork.attach(to);    

unitOfWork.begin();
from.withdraw(amount);
to.deposit(amount);
unitOfWork.commit();

この例のように、作業単位とリポジトリを個別に使用する必要があります。または、次のようにします。

  • Unit Of Work は内部でリポジトリを使用し、オブジェクトをロードする機能を持つべきですか?
  • ...または、リポジトリは内部で Unit Of Work を使用し、読み込まれたエンティティを自動的にアタッチする必要がありますか?

すべてのコメントは大歓迎です!

4

3 に答える 3

18

簡単に言えば、リポジトリが何らかの方法で UoW を使用しているということですが、これらのパターン間の関係は、最初に思われるほど具体的ではないと思います。Unit Of Work の目的は、基本的にデータベース関連の関数のグループをまとめて、アトミック ユニットとして実行できるようにする方法を作成することです。UoW を使用する際に作成される境界と、トランザクションによって作成される境界には関係があることがよくありますが、この関係はより偶然です。

一方、Repository パターンは、Aggregate Root 上のコレクションに似た抽象化を作成する方法です。多くの場合、リポジトリに表示される種類のものは、集計ルートのインスタンスのクエリまたは検索に関連しています。より興味深い質問 (そして答えは 1 つではありません) は、Aggregate のクエリ以外の処理を行うメソッドを追加することに意味があるかどうかです。一方では、複数の集計に適用される操作がある有効なケースがいくつかあります。一方、複数の集約に対して操作を実行している場合、実際には別の集約に対して単一のアクションを実行していると主張することもできます。データのクエリのみを行っている場合、UoW によって暗示された境界を本当に作成する必要があるかどうかはわかりません。

2 つのパターンは非常に異なるレベルの抽象化を扱っており、Unit Of Work の関与は、Aggregate がどのようにモデル化されるかに依存します。Aggregate は、永続性に関連する作業をそれが管理するエンティティに委任したい場合や、Aggregate と実際の ORM の間に別の抽象化レイヤーが存在する場合があります。集合体/エンティティ自体が持続性を扱っている場合、リポジトリもその持続性を管理することが適切な場合があります。そうでない場合、リポジトリに UoW を含める意味がありません。

組織外で一般に消費されるものを作成したい場合は、ユーザーのニーズに依存せずに、ORM と直接対話できるようにするか、リポジトリ インターフェイス/基本実装を作成することをお勧めします。あなたのORMの。これが内部的なもので、Aggregates.Entities で永続化作業を行っている場合、リポジトリで UoW を利用することは理にかなっています。汎用リポジトリの場合、適切に初期化および破棄されることを確認できるリポジトリ実装内から UoW オブジェクトへのアクセスを提供することは理にかなっています。その点で、単一の UoW 境界内で複数のリポジトリを利用したい場合もあります。

于 2011-05-28T04:30:50.907 に答える
4

リポジトリが内部で UoW を使用している場合は、アプローチを使用することをお勧めします。このアプローチには、特に Web アプリケーションの場合、いくつかの利点があります。

Web アプリケーションで UoW を使用する推奨パターンは、HTTP 要求ごとの Unit of Work (セッション) です。そのため、リポジトリが UoW を共有する場合、他のリポジトリから要求されたオブジェクト (複数の集約によって参照されるデータ ディクショナリなど) に対して第 1 レベルのキャッシュ (ID マップを使用) を使用できます。また、複数のトランザクションではなく 1 つのトランザクションのみをコミットする必要があるため、パフォーマンスの点ではるかにうまく機能します。

Java/.NET の世界で成熟した ORM である Hibernate/NHibernate のソース コードを見ることができます。

于 2011-05-23T08:45:46.207 に答える
2

良い質問!

あなたの仕事の境界がどうなるかによって異なります。複数のリポジトリにまたがる場合は、別の抽象化を作成して、複数のリポジトリが確実にカバーされるようにする必要があります。ドメイン駆動設計で定義されている小さな「サービス」レイヤーのようなものです。

作業単位がほぼリポジトリごとになる場合は、2 番目のオプションを使用します。

ただし、私の質問は、ORM を作成するときにリポジトリについてどのように心配できるかということです。これらは、Unit of Work のコンシューマーによって定義され、使用されますよね? その場合、作業単位を提供する以外に選択肢はありません。コンシューマーは作業単位にリポジトリを登録する必要があり、作業単位の境界を制御する責任も負います。ではない?

于 2011-05-19T13:58:28.470 に答える