Estou trabalhando em um sistema que permite aos administradores definir formulários que contêm campos. Os Formulários definidos são então utilizados para inserir dados no sistema. Às vezes, os formulários são preenchidos por um ser humano por meio de uma GUI, às vezes, o formulário é preenchido com base nos valores relatados por outro sistema.
Para cada campo, o administrador pode definir uma regra de validação que limita os valores permitidos para o campo. As regras de validação podem ser de "o valor inserido no campo deve ser verdadeiro ou falso" a "o valor inserido no campo deve existir na coluna A da tabela B no banco de dados". O Administrador pode a qualquer momento alterar a Regra de Validação para o Campo.
Nesse cenário, qual, na sua opinião, é o local mais adequado para validar se cada campo foi preenchido corretamente? Atualmente, tenho duas abordagens principais em mente:
Opção 1: validar no modelo de domínio
Cada objeto Field conteria a regra de validação especificada pelo administrador. Os objetos Field também teriam uma referência a um IValidator. Quando é feita uma tentativa de definir o valor do campo, o campo deve passar o valor fornecido e a regra de validação para o validador IV. Se o valor fornecido não for válido, uma ValidationException será lançada e tratada adequadamente na GUI / interface para o outro sistema.
Prós:
- Forte proteção contra campos que recebem valores atribuídos acidentalmente que violam a regra de validação
Contras:
A camada de acesso a dados precisa ser capaz de ignorar a validação e criar campos que violam a regra de validação atual. Apesar de o administrador alterar a regra de validação de um campo, ainda precisamos construir objetos de campo com base nos dados antigos, por exemplo, ao renderizar um formulário preenchido anos atrás. Isso pode ser resolvido armazenando a regra de validação atual sempre que armazenar o campo.
Nesse design, o modelo de campo tem um link indireto para o Data Access Layer / Repository por meio do IValidator. A injeção de Serviços / Repositórios em Modelos de Domínio parece ser geralmente desaprovada .
Opção 2: validar em um serviço
Tente garantir que todas as tentativas de definir o valor de um campo passem por um serviço que garanta a manutenção da regra de validação. Se a regra de validação for violada, lance uma ValidationException.
Obviamente, a Camada de Acesso a Dados não usaria o Serviço ao criar objetos de Campo que haviam sido persistidos anteriormente no banco de dados.
Prós:
Não viola o pensamento "não injete Serviços / Repositórios nos seus Modelos de Domínio".
Não há necessidade de persistir a regra de validação atual ao persistir no campo. O Serviço pode simplesmente procurar a Regra de Validação atual para o Campo; ao analisar os dados do histórico, o valor do campo não será alterado.
Contras:
- Não há garantia de que toda a lógica que deve usar o Serviço para definir o valor do Campo realmente o faça. Eu vejo isso como uma grande desvantagem; tudo o que parece ser necessário é alguém que esteja escrevendo "thisField.setValue (thatField.getValue ())" e a Regra de validação deste campo pode ser violada sem que ninguém seja mais sábio. Isso pode ser mitigado, garantindo que o valor do Campo corresponda à Regra de Validação quando a Camada de Acesso a Dados estiver prestes a persistir.
Atualmente, prefiro a Opção 1 ao invés da Opção 2, principalmente porque vejo isso como lógica de negócios e sinto que a Opção 2 representa um risco maior de introduzir dados incorretos no sistema. Qual opção você prefere ou existe outro design que se encaixa nesse cenário melhor do que as duas opções descritas?
Editar (complexidade das validações)
Os casos de validação que surgiram no momento são relativamente simples; o valor do campo deve ser, por exemplo, numérico, uma data, uma data com uma hora ou um valor existente em uma coluna do banco de dados. No entanto, suspeito que a complexidade aumente gradualmente ao longo do tempo. Por exemplo, a solução de validação precisa ser construída com a internacionalização em mente - coisas como Datas podem ser inseridas em uma sintaxe específica do local.
Decidi continuar com a opção 1 por enquanto, tentando tomar cuidado para não atribuir muitas responsabilidades ao modelo de domínio. Aqueles que enfrentam uma situação semelhante também podem querer consultar as questões relacionadas Validação e autorização na arquitetura em camadas e Validação de entrada de dados - Onde? Quanto? .