私にとって、リポジトリは、ORMまたは他のDB永続層と組み合わせて、次のような欠点があります。
- 作業単位の隠蔽。UoWはプログラマーがコーディングする必要があり、UoW境界と場合によってはコミットポイントを定義せずに、ユーザーがクエリと変更を行うだけのバックグラウンドで、一種の魔法として実装されることはほとんどありません。時々、UoWは、各リポジトリアクセス方法でマイクロUoW(NHibernateセッションなど)に減らすことによって放棄されます。
- 永続的な無知を隠蔽するか、最悪の場合、破壊する:「Load()」、「Get()」、「Save()」または「Update()」などのメソッドは、個々のオブジェクトを送信するかのように、即時の単一オブジェクト操作を提案しますSQL / DML、またはファイルを操作するかのように。実際、たとえば、これらの紛らわしい名前を持つNHibernateメソッドは、通常、個別のアクセスを行わず、遅延ロードまたは挿入/更新バッチ(永続性無視)のためにキューに入れます。プログラマーは、なぜ即座にDB操作を取得せず、永続性の無知を強制的に解体せず、パフォーマンスを低下させ、システムを実際に(大いに!)悪化させるために大きな努力を払うのか疑問に思うことがあります。
- 制御されない成長。単純なリポジトリには、特定のニーズに合わせてますます多くのメソッドが蓄積される場合があります。
といった:
public interface ICarsRepository /* initial */
{
ICar CreateNewCar();
ICar LoadCar(int id); // bad, should be for multiple IDs.
void SaveCar(ICar carToSave); // bad, no individual saves, use UoW commit!
}
public interface ICarsRepository /* a few years later */
{
ICar CreateNewCar();
ICar LoadCar(int id);
IList<ICar> GetBlueCars();
IList<ICar> GetRedYellowGreenCars();
IList<ICar> GetCarsByColor(Color colorOfCars); // a bit better
IList<ICar> GetCarsByColor(IEnumerable<Color> colorsOfCars); // better!
IList<ICar> GetCarsWithPowerBetween(int hpFrom, int hpTo);
IList<ICar> GetCarsWithPowerKwBetween(int kwFrom, int kwTo);
IList<ICar> GetCarsBuiltBetween(int yearFrom, int yearTo);
IList<ICar> GetCarsBuiltBetween(DateTime from, DateTime to); // some also need month and day
IList<ICar> GetHybridCarsBuiltBetween(DateTime from, DateTime to);
IList<ICar> GetElectricCarsBuiltBetween(DateTime from, DateTime to);
IList<ICar> GetCarsFromManufacturer(IManufacturer carManufacturer);
bool HasCarMeanwhileBeenChangedBySomebodyElseInDb(ICar car); // persistence ignorance broken
void SaveCar(ICar carToSave);
}
4.神の危険オブジェクト:モデルまたはデータアクセスレイヤーのすべてをカバーする1つの神クラスを作成したくなるかもしれません。リポジトリクラスにはCarメソッドだけでなく、すべてのエンティティのメソッドが含まれます。
私の意見では、多くの単一目的メソッドの巨大な混乱を回避するために、少なくともいくつかのクエリの機会を提供する方が良いです。それがLINQ、独自のクエリ言語、またはORMから直接取得されたものであっても(OK、一種のカップリング問題...)。