Gerenciando validações do lado do cliente e do servidor em um único local

17

Estou 100% satisfeito com o caso de que definitivamente se deve usar validações de dados do lado do cliente e do servidor.

No entanto, nas estruturas e ambientes em que trabalhei, as abordagens que vi nunca foram SECA. Na maioria das vezes, não há plano ou padrão - as validações são escritas na especificação do modelo e as validações são escritas no formulário na exibição. (Nota: A maior parte da minha experiência em primeira mão é com Rails, Sinatra e PHP com jQuery)

Pensando bem, parece que não seria difícil criar um gerador que, dado um conjunto de validações (por exemplo, nome do modelo, campo (s), condição), pudesse produzir o material necessário para o cliente e para o servidor. Como alternativa, essa ferramenta pode obter as validações do lado do servidor (como o validatescódigo em um modelo ActiveRecord) e gerar validações do lado do cliente (como os plugins jQuery, que serão aplicadas ao formulário.

Obviamente, o exposto acima é apenas um "ei, eu tive essa idéia", e não uma proposta formal. Esse tipo de coisa é certamente mais difícil do que parecia quando a idéia me atingiu.

Isso me leva à pergunta: como você abordaria o design de uma técnica "escreva uma vez, execute no servidor e no cliente" para validação de dados?

Subtópicos relacionados: Existem ferramentas como essa para estruturas específicas ou tecnologias cliente-servidor? Quais são as principais armadilhas ou desafios ao tentar manter apenas um conjunto de validações?

asfallows
fonte

Respostas:

6

Na minha experiência limitada, os pontos em que a validação é necessária são

  1. O nível de apresentação usando HTML,
  2. no nível pós-apresentação (ou seja, validação Javascript),
  3. no nível da combinação em que as interações entre vários campos precisam ser validadas juntas,
  4. no nível da lógica de negócios e
  5. no nível do banco de dados.

Cada um deles possui diferentes idiomas, horários e gatilhos. Por exemplo, faz pouco sentido validar um campo antes que todo o registro esteja em um estado consistente, a menos que você queira validar apenas uma parte. Restrições no nível do banco de dados devem ser aplicáveis ​​apenas no final antes de uma confirmação e não podem ser prontamente feitas por partes.

Um conceito relacionado é que a representação de dados varia entre cada um dos níveis. Um exemplo simples é que um navegador da Web representa um pedaço de texto como, talvez, o CP1290, enquanto o banco de dados o representa em UTF-8; os comprimentos das duas cadeias diferem, portanto, aplicar restrições de comprimento fica complicado.

BobDalgleish
fonte
Sim, diferentes linguagens e estruturas tornam isso impraticável. Não é "desfazível" porque, com recursos suficientes, isso poderia ser feito, mas escrever conversores automáticos para e entre idiomas é uma tarefa ENORME. Fazer isso em um prazo razoável e depois mantê-lo à medida que as tecnologias relevantes mudam seria muito trabalhoso.
precisa
É definitivamente verdade que muitas validações no servidor (por exemplo, a exclusividade de um campo) não podem ser executadas no navegador. No entanto, também é verdade que todas as validações do lado do cliente precisam ser repetidas no servidor, pois você não pode confiar no cliente. É aí que vejo as coisas de SECAGEM serem especialmente úteis. Por exemplo, eu pude ver uma gema que estende o Rails ' form_forpara fornecer automaticamente o código de validação do lado do cliente, sendo muito útil.
Dan
5

Uma consideração que geralmente limita as soluções é a ida e volta da rede. O cliente deve validar os dados do usuário sem enviar uma mensagem pela rede. Em outras palavras, quando o usuário pressiona o botão de envio, o cliente deve validar os dados localmente.

Primeiro, vamos assumir que não temos essa limitação. Poderíamos nos comunicar com um endpoint de rede que seja bom em articular problemas de validação. Por exemplo, quando você envia seu novo registro de Usuário para ele, em vez de responder com um código de erro HTTP baunilha, ele pode retornar uma resposta JSON detalhada, detalhando os problemas e o cliente atualiza a exibição de maneira inteligente para refletir os problemas encontrados. O terminal desempenha o papel de um gateway de validação.

É SECO, mas não sem inconvenientes. Primeiro, depende da viagem de ida e volta da rede, tributando nosso servidor com validações que poderiam ter sido tratadas do lado do cliente. Segundo, o design antecipa que todas as operações CRUD ocorrerão por meio de nossos pontos de extremidade, mas e quando desenvolvedores e processos ignoram nossa camada de acesso a dados indo diretamente para o banco de dados ?

Vamos revisitar nossa solução para superar esses inconvenientes. Em vez disso, vamos armazenar e comunicar nossas validações como metadados:

{field: 'username', type: 'required'}
{field: 'username', type: 'unique'} //requires a network roundtrip
{field: 'password', type: 'length', min: 10, max: 50}
{field: 'password', type: 'contains', characters: ['upper', 'special', 'letter', 'number']}

O cliente e o servidor teriam algum mecanismo (por exemplo, um mecanismo) para interpretar e aplicar esses dados. (Alguns chamam isso de mônada livre, pois separa a parte declarativa do intérprete.) No JavaScript, poderíamos mapear cada informação para funções de trabalho. Para inicializar, podemos ensinar qualquer camada de nossa arquitetura, incluindo nosso banco de dados, a aplicar validações de forma consistente.

Mario T. Lanza
fonte
Como você descreve um campo quando um campo é representado de maneira diferente no navegador da Web, transporte, idioma de implementação e banco de dados? Por exemplo, o número de bytes necessários para representar um campo de sequência varia ao usar CP1290 (IE), UTF-8 (JSON), UTF-8 (C #) ou UCS-16 (Oracle). O que significa uma restrição de comprimento? Mais importante para o navegador, quando a representação de caracteres depende do navegador e do sistema operacional?
BobDalgleish
Essas restrições são apontadas como um modelo mental para os seres humanos. Seu trabalho como programador é abstrair as diferenças na máquina, para que a pessoa não precise se preocupar com diferenças técnicas.
Mario T. Lanza
Você perdeu completamente o objetivo. Até agora, ninguém apresentou uma abstração que permita a validação de ponta a ponta, com uma especificação. No OP, "escrever uma vez" implica que ter cláusulas diferentes que tratam de estágios diferentes não se qualifica. Da mesma forma, não vejo nada na sua validação proposta que lide com a validação entre campos ou interobjetos.
BobDalgleish
As validações entre campos / objetos não são muito complicadas. Os metadados representam apenas o relacionamento. Escrever uma vez implica em escrever uma única validação uma vez e aplicá-la em vários sites, o que faz. Você adiciona metadados a uma tabela. Esses metadados são recebidos por qualquer site e uma classe / utilitário / mecanismo simples impõe a restrição.
Mario T. Lanza
1
Essa linguagem de validação seria extremamente útil. Poderia substituir talvez um terço do código envolvido em aplicativos da Web intensivos em UI.
BobDalgleish
2

Uma maneira seria usar a mesma linguagem / estrutura no servidor e no cliente.

Por exemplo

Node.js :: Cliente / Servidor em JavaScript GET :: Cliente / Servidor em Java

Nesse caso, a maior parte do código "Objeto de Domínio" seria comum, incluindo validação. O Framework invocará o código conforme necessário. Por exemplo, o mesmo código seria chamado no navegador antes de "enviar" e no serviço Web do servidor.

EDIT (junho / 2014): Com o Java 8, agora é fácil integrar também o código de validação JS nos aplicativos Java. O Java 8 possui um novo mecanismo de execução JS que é mais permanente (por exemplo: utiliza invokeDynamic).

Shamit Verma
fonte
Quando se trata do banco de dados SQL, não tenho certeza de como isso funcionaria.
precisa
Também não resolve o problema de o navegador e o sistema operacional afetarem o domínio de entrada.
BobDalgleish
@Micheal Durrant, Para validação de banco de dados, são implementadas como restrições de banco de dados (como chave estrangeira, exclusiva etc). BobDalgleish, 1. O problema da compatibilidade do navegador / SO pode ser atenuado usando uma biblioteca que ajusta o tempo de execução de acordo com o navegador (como o Sencha) 2. A comatibilidade do navegador em geral não afeta partes "lógicas" do código, como validação, problemas de compatibilidade geralmente são em torno da renderização DOM / UI.
Shamit Verma
0

Eu só estava pensando no mesmo problema. Eu estava pensando em usar ANTLR para obter uma árvore de sintaxe abstrata em c # e javascript. A partir daí, você usa caminhantes para aplicar as ações especificadas no idioma aos objetos a serem validados.

Então, você pode armazenar uma descrição da validação necessária onde quiser - possivelmente no banco de dados.

É assim que eu abordaria o problema.

Marcus
fonte