Evite o padrão de repositório para operações não relacionadas à persistência

English version available here.

Hoje quero compartilhar um pouco sobre o padrão Repositório e Fachada. Tentarei explicar suas diferenças, pois parece haver alguns equívocos comuns sobre eles.

Repositório

Vamos tentar definir um repositório, a partir do dicionário: um lugar, sala ou contêiner onde algo é depositado ou armazenado. Em termos de programação, o conceito pode ser definido como uma classe responsável por lidar com operações CRUD (criar, ler, atualizar e deletar) para um modelo de domínio específico por meio do uso de uma ou mais fontes de dados.

Pela definição acima, podemos ver que devemos usar repositórios apenas para operações CRUD, o que significa que podemos ter um UserRepository e nunca umAuthenticationRepository, simplesmente porque a autenticação não descreve um conjunto de operações CRUD (assumindo que estamos falando sobre operações de login/registro).

Um erro comum que tenho visto é que algumas pessoas definem repositórios para operações de acesso ao sistema por exemplo:

abstract class AuthenticationRepository {

  Future login(String username, String password);

  Future register(String name, String email, String password);
}

Resumo #1: Apenas use o padrão de repositório para operações CRUD

Claramente, essas não são operações para armazenar/recuperar dados e, portanto, nunca devemos declará-las em um repositório. E agora? Fachadas!

Fachadas / Facade pattern

Pela Wikipedia, podemos definir uma fachada como um objeto que serve como uma interface frontal mascarando um código subjacente mais complexo.

Agora vamos definir um repositório: um Repositório é um tipo de fachada especializada em mascarar/abstrair operações CRUD complexas especificamente entre fontes de dados.

Para comparar e contrastar, fachadas são mais gerais do que repositórios - eles podem ser usados para qualquer coisa diferente de persistência. Você pode usar fachadas para abstrair interações complexas em APIs de vários bancos. Por exemplo:

// Or BankOperationsFacade.
abstract class BankOperations {

  Future payTelecomService(double amount, String cardId, String serviceId);

  Future transfer(double amount, String senderId, String recipientId);
}

// Custom implementation for XBank interaction goes here.
class XBankOperations extends BankOperations { }

// Custom implementation for YBank interaction goes here.
class YBankBOperations extends BankOperations { }

Resumo #2: Repository é um tipo mais especializado de Facade

Vamos revisar o primeiro trecho de código apresentado em nosso artigo, mas, desta vez, iremos refatorar o nome da classe para ser algo mais significativo.

// Or any other meaningful name.
abstract class AuthenticationFacade {

  Future login(String username, String password);

  Future register(String name, String email, String password);
}

Principais conclusões

  • As fachadas podem ser aplicadas a qualquer coisa que não seja baseada na persistência
  • Repositórios são para envolver a comunicação com uma ou mais fontes de dados e abstrair isso do usuário do repositório
  • Fachadas são mais genéricas do que repositórios.

É importante fazer uso desses conceitos de maneira adequada para evitar escrever códigos difíceis de entender e para manter uma base de código saudável.

Espero que isso ajude você de alguma forma; por favor, deixe-me saber sua opinião na seção de comentários.

14