Para mí, los repositorios, combinados con ORM u otras capas de persistencia DB, tienen estas desventajas:
- Encubrimiento de unidades de trabajo. El programador debe codificar UoW y rara vez se puede implementar como una especie de magia en segundo plano, donde el usuario simplemente realiza consultas y modificaciones, sin definir los límites de UoW y posiblemente el punto de confirmación. A veces, los UoW se abandonan reduciéndolos a micro UoW (por ejemplo, sesiones de NHibernate) en cada método de acceso al Repositorio.
- Enmascarar o, en el peor de los casos, destruir la ignorancia de persistencia: métodos como "Load ()", "Get ()", "Save ()" o "Update ()" sugieren operaciones inmediatas de un solo objeto, como si se enviara un objeto individual SQL / DML, o como si estuviera trabajando con archivos. De hecho, por ejemplo, los métodos de NHibernate, con estos nombres engañosos, generalmente no hacen acceso individual, sino que ponen en cola la carga diferida o el lote de inserción / actualización (Ignorancia de persistencia). A veces, los programadores se preguntan por qué no obtienen operaciones inmediatas de base de datos y rompen por la fuerza la ignorancia de persistencia, lo que mata el rendimiento y utiliza grandes esfuerzos para empeorar el sistema (¡mucho!).
- Crecimiento descontrolado. Un repositorio simple podría acumular más y más métodos para satisfacer necesidades específicas.
Como:
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. Objeto Peligro de Dios: es posible que tengas la tentación de crear una clase de dios que cubra todo tu modelo o capa de acceso a datos. La clase de repositorio no solo contendría métodos Car, sino también métodos para todas las entidades.
En mi opinión, es mejor ofrecer al menos algunas oportunidades de consulta, para evitar el gran lío de muchos métodos de propósito único. No importa si es LINQ, un lenguaje de consulta propio o incluso algo tomado directamente del ORM (OK, tipo de problema de acoplamiento ...).