Validação de arquitetura limpa no domínio vs camada de persistência de dados?


12

Estou estudando limpeza e, como resultado, estou repensando bastante de maneira significativa como projeto e escrevo software.

No entanto, ainda estou lutando com regras comerciais, como "salvar atualizações de algum item, carregar primeiro. Toda a lista de itens que tenho permissão para exibir / editar etc., confirme se esse item está na lista, e que a categoria do item não está atualmente bloqueada para uso (e outras regras, etc, etc) ".. porque essa é uma regra de negócios (complexa, mas não atípica) e, portanto, deve ser tratada no domínio do aplicativo, em vez de empurrar a lógica de negócios para dentro. a camada db / persistence.

No entanto, parece-me que, para verificar com eficiência essas condições, geralmente é melhor lidar com uma consulta db bem criada, em vez de carregar todos os dados no domínio do aplicativo ...

Sem a otimização prematura, qual é a abordagem recomendada ou alguns artigos do tio Bob que lidam com essa pergunta? Ou ele diria "validar no domínio até que se torne um problema"?

Estou realmente lutando para encontrar bons exemplos / amostras para algo que não seja o mais básico dos casos de uso.

Atualizar:

Olá a todos, obrigado pelas respostas. Eu deveria ter sido mais claro, estou escrevendo um software (principalmente para aplicativos da Web) há muito tempo e definitivamente já experimentei e concordo com todos os tópicos que você descreve coletivamente (valide pelo back-end, não confie nos dados do cliente, em geral busque a eficiência bruta apenas quando necessário, mas reconheça os pontos fortes das ferramentas db quando disponíveis, etc etc) e tenha passado pelo ciclo de vida de aprendizado do desenvolvedor de "junte tudo" para "construir um controlador de gordura gigante com aplicativos de camadas N" tendências de código e agora realmente gostando e investigando o estilo de responsabilidade limpa / única etc., basicamente como resultado de alguns projetos recentemente que evoluíram para regras de negócios bastante desajeitadas e amplamente distribuídas à medida que os projetos evoluíam e outros requisitos do cliente vieram à tona.

Em particular, estou analisando a arquitetura de estilo limpo no contexto da criação de APIs REST para funcionalidade voltada para o cliente e para uso interno, onde muitas das regras de negócios podem ser muito mais complexas do que basicamente todos os exemplos que você vê na rede (mesmo pelos próprios caras da arquitetura Clean / Hex).

Então, eu acho que estava realmente perguntando (e falhei em declarar claramente) sobre como o Clean e uma API REST se acomodariam juntos, onde a maioria das coisas do MVC que você vê atualmente tem validadores de solicitação de entrada (por exemplo, biblioteca FluentValidation no .NET), mas onde muitos minhas regras de "validação" não são muito "é uma string com menos de 50 caracteres", mas mais "pode ​​esse usuário que chama esse banco de dados / interator executar esta operação nesta coleta de dados, dado que algum objeto relacionado está atualmente bloqueado pelo Time X até o final do mês etc etc "... esse tipo de validação profundamente envolvida, onde MUITOS objetos de domínio de negócios e regras de domínio são aplicáveis.

Devo girar essas regras para um tipo específico de objeto Validator-objeto para acompanhar cada interator-caso de usuário (inspirado no projeto FluentValidator, mas com mais lógica de negócios e acesso a dados envolvidos), devo tratar a validação como um Gateway, devo coloque essas validações em um gateway (que eu acho errado), etc etc.

Para referência, estou publicando vários artigos como este , mas Mattia não discute muito sobre validação.

Mas acho que a resposta curta para minha pergunta é muito parecida com a resposta que aceitei: "Nunca é fácil e depende".


2
Muitas vezes há uma diferença entre ser "correto" e ser "prático". Dada a escolha, qual você prefere?
Robert Harvey

"load Toda a lista de itens" não parece uma regra de negócios, parece estar mergulhando demais nos detalhes da implementação. Se você pode satisfazer a regra usando uma consulta db, sem carregar nada, por que a regra diz "carregar"?
Pare de prejudicar Monica

Respostas:


31

A validação da entrada de dados é uma daquelas coisas em que todo mundo começa a tentar torná-la pura e limpa e (se for inteligente) acaba desistindo, porque existem muitas preocupações concorrentes.

  • A camada da interface do usuário deve fazer algumas formas de validação ali mesmo na página / formulário do cliente para fornecer feedback em tempo real ao usuário. Caso contrário, o usuário gasta muito tempo aguardando feedback enquanto uma transação é lançada na rede.

  • Como o cliente geralmente é executado em uma máquina não confiável (por exemplo, em quase todos os aplicativos da Web), essas rotinas de validação devem ser executadas novamente no lado do servidor em que o código é confiável.

  • Algumas formas de validação estão implícitas devido a restrições de entrada; por exemplo, uma caixa de texto pode permitir apenas entrada numérica. Isso significa que você pode não ter um "é numérico?" validador na página, mas você ainda precisará de um no back-end, em algum lugar, pois as restrições da interface do usuário podem ser contornadas (por exemplo, desativando o Javascript).

  • A camada da interface do usuário deve fazer algumas formas de validação no perímetro do serviço (por exemplo, código do servidor em um aplicativo da Web) para isolar o sistema contra ataques de injeção ou outras formas maliciosas de entrada de dados. Às vezes, essa validação não está na sua base de código, por exemplo, validação de solicitação do ASP.NET .

  • A camada da interface do usuário deve fazer algumas formas de validação apenas para converter os dados inseridos pelo usuário em um formato que a camada de negócios possa entender; por exemplo, ele deve transformar a cadeia "26/06/2017" em um objeto DateTime no fuso horário apropriado.

  • A camada de negócios deve fazer a maioria das formas de validação porque, ei, elas pertencem à camada de negócios, em teoria.

  • Algumas formas de validação são mais eficientes na camada do banco de dados, especialmente quando são necessárias verificações de integridade referenciais (por exemplo, para garantir que um código de estado esteja na lista de 50 estados válidos).

  • Algumas formas de validação devem ocorrer no contexto de uma transação de banco de dados devido a preocupações de simultaneidade, por exemplo, a reserva de um nome de usuário exclusivo deve ser atômica, para que outro usuário não o pegue enquanto estiver processando.

  • Algumas formas de validação só podem ser executadas por serviços de terceiros, por exemplo, ao validar se um código postal e um nome de cidade estão juntos.

  • Em todo o sistema, verificações nulas e conversões de conversão de dados podem ocorrer em várias camadas, para garantir modos razoáveis ​​de falha na presença de falhas de código.

Eu já vi alguns desenvolvedores tentarem codificar todas as regras de validação na camada de negócios e, em seguida, fazer com que as outras camadas chamem para extrair as regras de negócios e reconstruir a validação em uma camada diferente. Em teoria, isso seria ótimo porque você acaba com uma única fonte de verdade. Mas nunca vi essa abordagem complicar desnecessariamente a solução, e muitas vezes termina muito mal.

Portanto, se você está se matando tentando descobrir para onde vai o seu código de validação, seja aconselhado - em uma solução prática para até um problema moderadamente complexo, o código de validação acabará indo para vários lugares.


Se você considerar que gerencia a interface do usuário com todos os comentários do usuário, basta enviar a maior parte da verificação de validação no banco de dados e manter apenas o que não pode fazer na camada de negócios. Problema surge se você criar uma API de back-end completo com uma solução de problemas de mensagens muito detalhada.
Walfrat

2

A validação faz parte da camada de negócios.

O ponto é: a lógica comercial nos DAOs invalidará o conceito de DAOs. Fazer a validação em qualquer camada superior resultará em validação redundante se você chamar operações de negócios de outra base de dados.

Talvez você avalie alguma segurança na interface do usuário. Mas isso é opcional, pois os objetos de domínio seguro farão o trabalho importante. Na interface do usuário, os Componentes ficarão visíveis ou invisíveis, dependendo das permissões que o usuário conectado no momento possui. Mas isso é apenas parte da experiência do usuário. Você não deseja que o usuário se depare com exceções de segurança sempre que tentar realizar uma ação que não está autorizado a executar.


2

Convém verificar sua perspectiva sobre quem está fazendo o que em relação à validação. É o DB, onde você sabe que está trabalhando com o DB? Ou é um serviço (que é apoiado e controlado pelas operações do banco de dados). No meu projeto, toda raiz agregada tem uma lista de grupos que podem lê-la e uma lista de modificadores. Quando o código procura uma raiz específica ou uma lista de raízes que o usuário pode ver, todos os detalhes ficam ocultos por trás de um serviço que leva o ID do usuário e as partes extras do contexto de pesquisa, como onde o bloco começa com "blá". O código não se importa que o banco de dados execute uma verificação existente para verificar se os grupos de usuários existem nos grupos de leitores. Apenas espera uma lista com ou sem conteúdo, com base no que o serviço, definido apenas por contrato, fornece.

Isso se aplica a todas as camadas. A uniformidade da validação é a chave. Coloque o máximo de sua validação no domínio possível. Retorne restrições com sua API. Eu sou o fim, não pense em restrições provenientes da biblioteca X ou do armazenamento Z, mas do serviço.


0

Se alguma lógica de validação for expressa da maneira mais simples e clara na forma de uma consulta ao banco de dados, vá em frente, você tem sua resposta. Mas a eficiência só deve ser uma preocupação se você tiver um problema de desempenho conhecido, caso contrário, é uma otimização prematura.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.