Artigo

O que e e quando devemos utilizar o padrao Repository?

Rodrigo Branas
Rodrigo Branas
10 dez 2023·3 min de leitura
#repository#design-patterns

O proposito do padrao Repository vai além de simplesmente separar as responsabilidades relacionadas com a persistencia. Ele e responsavel pela mediacao e o desacoplamento entre o Domain Model, ou seja, objetos de domínio, e as operacoes de persistencia de cada um desses objetos.

Isso quer dizer que so faz sentido utilizar o padrao Repository em conjunto com o Domain Model? Exatamente, caso contrario o que ele estaria persistindo seria algo diferente de um objeto de domínio e o padrao perderia o sentido e acabariam sendo utilizados outros padrões de persistencia como o Table Data Gateway ou Data Access Object (também conhecido como DAO), que são orientados a tabelas.

Design Patterns: Transaction Script vs Domain Model

Para entender o Repository e necessario compreender antes que existem dois caminhos em termos de design. Um deles abstrai as regras de negocio em procedimentos, metodos e funcoes, transferindo o fluxo de execução entre cada uma delas, apenas passando parametros e sem a utilização de abstracoes. De acordo com a obra classica do Martin Fowler, Patterns of Enterprise Application Architecture, essa abordagem se chama Transaction Script e e conhecida por ser anemica, ou seja, ainda que seja implementada utilizando uma linguagem Orientada a Objetos o design acaba sendo procedural.

Outra abordagem e o Domain Model, que e utilizado no Clean Architecture e no Domain-Driven Design, onde a complexidade e distribuida em objetos de domínio, protegendo a invariancia por meio do encapsulamento e a exposicao apenas do comportamento necessario para realizar a mutacao de estado, reduzindo o acoplamento e dessa forma a fragilidade.

O Problema: Como Persistir Objetos de Domínio?

Isso cria um problema: como fazer para persistir esses objetos de domínio?

O padrao Repository existe exatamente para isso, realizar a persistencia sem que as outras camadas precisem se preocupar com isso.

Exemplo Prático: Classe User

class User {
  private email: Email;
  private password: Password;
  private status: string;

  updatePassword(newPassword: string) {
    if (this.status === "blocked") throw new Error("Cannot change password of a blocked user");
    this.password = new Password(newPassword);
  }

  getPassword() {
    return this.password.getValue();
  }
}

Repare que a classe User e composta por Email e Password, criando um grupo de objetos de domínio. No Domain-Driven Design isso se chama Aggregate e e exatamente esse grupo que e persistido no Repository.

Dessa forma, teremos um UserRepository:

interface UserRepository {
  save(user: User): Promise<void>;
  update(user: User): Promise<void>;
  get(userId: string): Promise<User>;
  list(): Promise<User[]>;
}

Pergunta Frequente: updatePassword no Repository?

Ah, mas eu queria simplesmente mudar a senha, não posso ter um updatePassword em UserRepository?

Aqui entra o conceito de Domain Model e da proteção da invariancia. Repare que utilizamos um Value Object para abstrair a senha e para defini-la e necessario causar uma mutacao no objeto User que passara pelo objeto Password.

class Password {
  private value: string;

  constructor(password: string) {
    if (password.length < 8) throw new Error("Minimum length is 8");
    if (!password.match(/\d+/g)) throw new Error("Password must have at least one number");
    if (!password.match(/[A-Za-z]+/g)) throw new Error("Password must have at least one letter");
    this.value = password;
  }

  getValue() {
    return this.value;
  }
}

Se o metodo updatePassword existisse ele quebraria a invariancia do objeto User, levando-o a um estado invalido, ou seja, permitindo que alguém modifique a senha de um usuário bloqueado ou utilize uma senha com menos de 8 caracteres e que não contem uma combinação de números e letras.

Preservando a Integridade

O padrao Repository tem em sua interface o objeto User, impedindo que qualquer mutacao de estado seja feita sem passar pelas regras de negocio implementadas nos objetos de domínio, preservando a integridade do Domain Model.

Conclusão: Não é Certo ou Errado

Utilizar o padrao Repository não tem nada a ver com certo ou errado, e simplesmente resultado da escolha de uma estratégia de design, que também não esta certa ou errada, simplesmente vai apresentar vantagens e desvantagens dependendo da situação. Em um domínio muito complexo, utilizar Transaction Script faz com que a complexidade se acumule e com que seja mais difícil manter e evoluir o código-fonte com o passar do tempo enquanto o Domain Model proporciona uma melhor distribuição da complexidade, facilidade em testar no nível de unidade mas ao mesmo tempo requer uma capacidade maior de abstracao por parte da equipe.

Continue aprendendo

Já conhece nossas formações?

Os desenvolvedores que vão se manter no futuro são os que dominam a Inteligência Artificial e são arquitetos de software. Aprenda como ser esse tipo de desenvolvedor.

Cookies e privacidade

Utilizamos cookies para melhorar sua experiência, analisar o tráfego do site e personalizar conteúdo. Você pode aceitar todos, rejeitar ou personalizar suas preferências.