segunda-feira, 4 de agosto de 2014

Problemas com Repository e ORM

Em um post anterior eu evidenciei uma tendência de se encapsular frameworks em classes da própria aplicação. Dei uma atenção especial ao padrão Repository utilizado com ORM’s, e nesse post resolvi  destacar outros problemas que podem ocorrer com esse padrão.

Nem sempre é fácil identificar a responsabilidade

Quando estamos definindo os métodos do repositório os métodos básicos são fáceis de definir:
  1. GetById;
  2. Save (InsertOrUpdate);
  3. Delete;
  4. GetBy(Filter filters);

Vamos pegar um cenário onde você tenha um classe Customer e a classe Sale tendo cada uma delas a sua devida implementação do Repository.
Agora imagine um item do seu dashboard onde você exibe o total de vendas dos clientes:


Em qual repository você colocaria a implementação dessa consulta? Customer ou Sale?

Funcionalidades que requerem consultas e escritas no banco de dados que cruzam as fronteiras estabelecidas pelo padrão é algo muito comum. Quando surgem cenários desse tipo alguns utilizam estrategias que podem degradar a performance da aplicação como o Select N+1.

Dificuldade para resolver problemas de Performance

O Select N + 1 significa que você foi mais de uma vez no banco de dados para obter dados, no exemplo acima tivemos as seguintes requisições no banco de dados.
  1. Obtém todos os clientes;
  2. Quando acionada a propridade Sales de o sistema foi no banco para obter as respectivas vendas, ou seja, se tivermos 10 clientes o sistema irá 10 vezes no banco buscar as vendas de dos clientes;
Até aqui esses problemas reportados não é culpa do padrão + ORM mas só do padrão. Com os repositories nós não conseguimos customizar o retorno do banco de dados para necessidades especificas, até por que isso foge um pouco das responsabilidades do padrão.

Como uma solução pra esses tipos de problemas muitos preferem expor recursos do ORM pelo Repository, como exemplo:
  • Enable/Disable Lazy Loading;
  • Multi Queries;
  • Operações em Batch;
O problema que isso se torna um “vazamento” da abstração que o Repository se propõe a fazer, se chegamos nesse ponto por que precisamos do padrão?

Organização e reaproveitamento de código

Alguns programadores ainda defendem a utilização do Repository por questões de organização e reaproveitamento de código e realmente processos de escrita e leituras duplicados não é legal. Pra resolver esses problemas já existem outros padrões bem interessantes pra ser utilizado (QueryObjects e CQRS).

Conclusão

Encapsular frameworks não é uma boa idéia, isso não significa que você não possa criar "facilitadores" para melhorar ou até mesmo contextualizar os frameworks para sua necessidade. Acredito que o ideal é sempre permitir que esses frameworks sejam utilizados diretamentes se necessário, assim todo o potencial dessas ferramentas sempre estará disponível.