Tenho uma dúvida com relação a validação de dados no Controller, trabalho num sistema legado onde é feito da seguinte forma:
São submetidos dados do front-end para o controller
No controller recebo o Form com os dados vindo do front-end
Realizo validações de negócio neste Form: nome não é nulo, cpf é válido, etc.
Instâncio o objeto de domínio com os dados já validados
Como vocês fazem: validam primeiro o form pra depois criar o objeto de domínio OU instanciam o objeto de domínio com dados brutos vindos do form e depois validam o objeto de domínio?
Em frameworks mais novos como Spring MVC, o objeto de domínio já vem instânciado automaticamente no controller, vejo como uma boa prática pois posso encapsular a validação das regras dentro do próprio objeto e não em todas as classes que eventualmente precisem utilizar o mesmo, tendo por base isso gostaria de melhorar meu código legado.
Eu gosto de fazer validações nas bordas do sistema. No caso, como o ponto de entrada do seu código é o controller, eu validaria antes de instanciar o objeto de domínio.
Contudo, se o framework pode fazer o mapeamento pra você, não vejo problemas em colocar a validação no próprio objeto de domínio. Eu pessoalmente não gosto, mas é só uma preferência minha. Estou acostumado com tipagem dinâmica e é mais simples fazer dessa forma. Gosto de separar a input do objeto real de domínio e essa separação me permite validar a input “crua”.
Quem segue DDD à risca vai te dizer que a validação tem que ocorrer dentro dos objetos de domínio. No exemplo do CPF que você mencionou, uma possibilidade é fazer uma classe específica chamada de CPF (um objeto de valor) e receber essa classe como argumento da sua entidade. Dá pra colocar a validação do CPF dentro da classe CPF. Assim a entidade (Pessoa ou algo assim, imagino eu) pode assumir que quando recebe um objeto da classe CPF, ele é válido. E assim por diante com as outras classes.
Validando antes de instanciar o objeto de domínio, você não replica várias vezes a mesma validação? Por exemplo numa inclusão/alteração? Ou deixa isso tudo encapsulado numa classe responsável por validar aquele objeto, algo assim para classe Pessoa: ValidacaoPessoa.
Eu lido muito com interceptors. No meu caso a validação ocorre antes mesmo de chegar no meu controller. O interceptor captura o request e checa se ele está de acordo com um schema pré definido. Se não passar na validação do schema, o próprio interceptor retorna um 400 pro cliente. Se passar a validação, aí sim o request continua e eventualmente chega no controller (depois de passar por todos os interceptors).
Não, porque a validação de cada parte dos dados está escrita numa função específica. É só reutilizar essas funções, compondo de acordo com o que é esperado da requisição. Se vai vir CPF e uma data, coloca essas duas validações.
Você pode criar uma classe específica para validar cada request que seu sistema aceita. Por exemplo: CreatePersonRequestValidator. Essa classe recebe um request (ou o body) da requisição de criar uma pessoa no sistema e chama as classes de validação necessárias para validar esse request (CPF, datas, nome, etc.).
Mesmo nesse caso, eu teria 2 classes separadas. Elas podem estar fazendo a mesma coisa internamente, mas elas tem razões diferentes para mudar. Se um dos dois requests muda e o outro não, aí começa a aparecer um monte de if dentro do código dessa classe para lidar com as diferenças. Acho melhor separar logo.
Pode deixar numa só também, mas é legal ter isso em mente. É um trade-off. Eu pessoalmente prefiro separar logo.