1. ホーム
  2. c#

[解決済み] リポジトリパターンを正しく使うには?

2023-05-11 11:31:08

質問

リポジトリをどのようにグループ化すればよいのでしょうか。asp.net mvc で見た例や私の本では、基本的にデータベーステーブルごとに 1 つのリポジトリを使用するようです。しかし、それは多くのリポジトリのように思えるので、後でモッキングや他のもののために多くのリポジトリを呼び出す必要があります。

だから、私はそれらをグループ化すべきだと推測しています。しかし、どのようにグループ化すればよいのかわかりません。

現在、私は登録用のリポジトリを作って、すべての登録作業を扱っています。しかし、4つのテーブルを更新する必要があり、以前はこれを行うために3つのリポジトリがありました。

例えば、テーブルの1つはライセンステーブルです。ユーザーが登録するとき、私はそのキーを見て、データベースに存在するかどうかを確認します。では、登録時以外に、このライセンス キーやそのテーブルの他の何かをチェックする必要がある場合はどうなるのでしょうか。

1つのスポットはログインです(キーが有効期限内であるかどうかをチェックします)。

このような場合、私はどうすればいいのでしょうか?コードをもう一度書き直しますか (DRY を破る)。これらの2つのリポジトリを一緒に結合して、メソッドのどれもが他の時点で必要とされないことを望みます(たとえば、userNameが使用されているかどうかをチェックするメソッドがあるかもしれませんが、それは他のどこかで必要になるかもしれません)。

サイトの2つの異なる部分のためにすべてのロジックを持つことは長くなり、ValidateLogin(), ValdiateRegistrationForm(), ValdiateLoginRetrievePassword() などの名前を持つ必要があると思うので、もし私がそれらを一緒にマージするなら、私は同じリポジトリに行く2つのサービス層を必要とするでしょう。

あるいは、とにかくリポジトリを呼び出して、奇妙な響きを持つ名前を持っているだけですか?

アプリケーションの多くのスポットに使用でき、なおかつ意味をなすような、十分に一般的な名前を持つリポジトリを作るのは難しいように思えますし、リポジトリの中で別のリポジトリを呼ぶことは良い習慣とは思えません。

どのように解決するのですか?

リポジトリパターンで遊んでいるときに私が間違っていたことのひとつは、あなたと同じように、テーブルがリポジトリに1対1で関連していると考えていたことです。ドメイン駆動設計のルールを適用すると、リポジトリをグループ化する問題はしばしば解消されます。

リポジトリは 集計ルート であるべきで、テーブルではありません。つまり、もしエンティティが単独で存在すべきではない場合(つまり Registrant があって、それが特定の Registration ) - それは単なる実体であり、リポジトリは必要ありません。それは、それが属する集約ルートのリポジトリを通して更新/作成/取得されるべきです。

もちろん - 多くの場合、リポジトリの数を減らすこのテクニック(実際には - ドメインモデルを構造化するためのテクニックです)は適用できません。あなたの例では License のコンテキストなしでそれらをチェックできるようにする必要があるため、集約ルートであるように見えます。 Registration のエンティティでチェックできる必要があるからです。

しかし、それはカスケード・リポジトリを制限するものではありません( Registration レポジトリを参照することができます。 License レポジトリを参照することができます(必要であれば)。それは参照することを制限するものではありません License リポジトリから直接(IoC を使って)参照することを制限するものではありません。 Registration オブジェクトを作成します。

ただ、技術によってもたらされる複雑さや、何かを誤解して設計を進めないようにしてください。リポジトリをグループ化する ServiceX でグループ化するのは良いアイデアではありません。

もっと良いのは、適切な名前を付けることです。 RegistrationService すなわち

しかし、サービスは一般に避けるべきものです。 貧弱なドメインモデル .

EDITです。

IoCを使い始めてください。依存関係の注入の苦痛を本当に和らげてくれる。

書く代わりに。

var registrationService = new RegistrationService(new RegistrationRepository(),  
      new LicenseRepository(), new GodOnlyKnowsWhatElseThatServiceNeeds());

が書けるようになります。

var registrationService = IoC.Resolve<IRegistrationService>();

P.s. いわゆる 共通サービスロケータ は、あくまで一例です。