Para mim, os repositórios, combinados com o ORM ou outras camadas de persistência do banco de dados, têm estas desvantagens:
- Encobrir unidades de trabalho. A UoW precisa ser codificada pelo programador e raramente pode ser implementada como um tipo de mágica em segundo plano, onde o usuário simplesmente faz consultas e modificações, sem definir os limites da UoW e, possivelmente, o ponto de confirmação. Às vezes, as UoW são abandonadas, reduzindo-as em micro UoW (por exemplo, sessões NHibernate) em cada método de acesso ao Repositório.
- Encobrir ou, na pior das hipóteses, destruir a ignorância de persistência: métodos como "Load ()", "Get ()", "Save ()" ou "Update ()" sugerem operações imediatas de um único objeto, como se enviassem indivíduos SQL / DML ou como se estivesse trabalhando com arquivos. De fato, por exemplo, os métodos NHibernate, com esses nomes enganosos, geralmente não fazem acesso individual, mas enfileiram para carregamento lento ou inserem / atualizam lotes (Persistence Ignorance). Às vezes, os programadores se perguntam por que não obtêm operações imediatas de banco de dados e quebram à força a ignorância da persistência, diminuindo o desempenho e usando grandes esforços para realmente piorar o sistema (muito!).
- Crescimento descontrolado. Um repositório simples pode acumular cada vez mais métodos para atender a necessidades específicas.
Tal 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 Perigo de Deus: você pode ser tentado a criar uma classe divina, cobrindo todo o seu modelo ou camada de acesso a dados. A classe de repositório não conteria apenas métodos Car, mas métodos para todas as entidades.
Na minha opinião, é melhor oferecer pelo menos algumas oportunidades de consulta, para evitar a enorme confusão de muitos métodos de uso único. Não importa se é LINQ, uma linguagem de consulta própria ou mesmo algo extraído diretamente do ORM (OK, tipo de problema de acoplamento ...).