Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Dúvida] Dúvida sobre utilização de interface de validação

Tenho uma dúvida quanto a possibilidade de utilização de interfaces para validação de dados na Arquitetura Clean.

Poderíamos encapsular a lógica de validação dentro de implementações de uma interface "Validacao" e chamá-la dentro do construtor da Entidade de domínio ou outra classe responsável pela criação da Entidade?

Por exemplo, suponha que tenhamos a seguinte interface: public interface Validacao<T>{ public void validar(T dado); } e dela tenho várias implementações que validam os campos da minha entidade, tomando como exemplo o usuário e os campos CPF, idade:

public class ValidaCpf implements Validacao<String> { @Override public void validar(String dado){ //lógica para validar CPF e Dígitos Verificadores } }

public class ValidaIdade implements Validacao<LocalDate> { @Override public void validar(LocalDate dado){ //lógica para validar idade } }

Caso seja possível, deveríamos instanciar cada Implementação individualmente ou existe alguma forma menos morosa de realizar?

3 respostas

Olá, Guilherme!

A sua ideia de usar interfaces para encapsular a lógica de validação na Clean Architecture é bastante interessante e está alinhada com os princípios de separação de responsabilidades e modularidade. Usar interfaces como Validacao<T> permite que você defina contratos claros para suas validações, além de facilitar a manutenção e a extensibilidade do código.

Você pode, sim, instanciar essas implementações de validação e chamá-las dentro do construtor da sua entidade de domínio ou de outra classe responsável pela criação da entidade. No entanto, instanciar cada implementação individualmente pode se tornar trabalhoso, especialmente se você tiver muitas validações.

Para tornar esse processo mais eficiente, você pode considerar o uso de um padrão de projeto como o "Composite", onde você cria uma classe que agrega várias implementações de validação e as executa de forma sequencial. Algo assim:

public class ValidacaoComposite<T> implements Validacao<T> {
    private List<Validacao<T>> validacoes = new ArrayList<>();

    public void adicionarValidacao(Validacao<T> validacao) {
        validacoes.add(validacao);
    }

    @Override
    public void validar(T dado) {
        for (Validacao<T> validacao : validacoes) {
            validacao.validar(dado);
        }
    }
}

Com essa abordagem, você pode adicionar todas as suas validações a uma instância de ValidacaoComposite e chamá-la uma única vez no construtor ou na classe de criação da entidade. Isso reduz a necessidade de instanciar cada validação individualmente.

Espero ter ajudado e bons estudos!

Obrigado pela ajuda, mas surgiu outra dúvida. Essa ideia de validar por interfaces surgiu do projeto do curso de Java e Spring Boot (projeto VolMed). Lá usamos o @Autowired para carregar todas as instâncias da interface de validação de um determinado DTO para fazer validações em vários campos diferentes a partir da iteração do método "validar(dto)".

Como poderia popular o Composite com todas as implementações de "Validacao"? isso seria feito por uma outra classe de domínio ou via bean por exemplo (nesse caso, ficaria atrelado ao framework)?

Uma sugestão fornecida pelo chat GPT seria a criação de um Factory para o composite:

public class ValidacaoEntidadeFactory {

    public ValidacaoComposite<Entidade> criarValidacaoComposite() {
        List<Validacao<Entidade>> validacoes = List.of(
            new ValidacaoImpl1(),
            new ValidadaoImpl2()
        );
        return new ValidacaoComposite<>(validacoes);  //Aqui ele usa o Collection.addAll();
    }
}

E transformar esse Factory em um Bean via @Configuration para posteriormente injetar junto das outras classes que foram mapeadas como Beans no configuration.

solução!

Como isso é um detalhe de domínio, poderia ser feito na própria entidade ou numa classe sevice, ou seja, a lista seria criada manualmente com os validadores no construtor mesmo.

Dessa forma o código fica totalmente isolado dos frameworks, mas a desvantagem é que vai precisar criar essa lista manualmente.

Justamente por conta disso entra um dilema: "isolar o domínio totalmente dos frameworks ou não?"

Pensando puramente em DDD e Clean Arch, o ideal seria separar, mas na prática, em projetos que utilizam frameworks, essa separação vai apenas deixar o código mais complexo e difícil de manter.