Gestione delle convalide lato client e lato server da un'unica posizione


17

Sono d'accordo al 100% nel caso in cui si debbano assolutamente utilizzare convalide dei dati sia lato client che lato server.

Tuttavia, nei framework e negli ambienti in cui ho lavorato, gli approcci che ho visto non sono mai stati ASCIUTTI. Il più delle volte non esiste un piano o modello: le convalide sono scritte nelle specifiche del modello e le convalide sono scritte nel modulo nella vista. (Nota: la maggior parte della mia esperienza di prima mano è con Rails, Sinatra e PHP con jQuery)

Rimuginandolo, sembra che non sarebbe difficile creare un generatore che, dato un insieme di convalide (ad esempio nome del modello, campo (i), condizione), potrebbe produrre sia il materiale necessario sul lato client che lato server. In alternativa, tale strumento potrebbe accettare le convalide sul lato server (come il validatescodice in un modello ActiveRecord) e generare convalide sul lato client (come i plug-in jQuery, che verrebbero quindi applicati al modulo.

Ovviamente, quanto sopra è solo un "ehi ho avuto questa idea" meditando, e non una proposta formale. Questo genere di cose è sicuramente più difficile di quanto sembrasse quando l'idea mi ha colpito.

Questo mi porta alla domanda: come affronteresti la progettazione di una tecnica "Scrivi una volta, esegui su server e client" per la convalida dei dati?

Argomenti correlati: esistono strumenti del genere per quadri particolari o tecnologie client-server? Quali sono i principali problemi o sfide nel tentativo di mantenere solo un set di convalide?

Risposte:


6

Nella mia esperienza limitata, i punti in cui sono richieste le convalide sono

  1. Il livello di presentazione usando HTML,
  2. a livello post-presentazione (ad es. validazione Javascript),
  3. a livello di combinazione in cui le interazioni tra più campi devono essere convalidate insieme,
  4. a livello di logica aziendale e
  5. a livello di database.

Ognuno di essi ha lingue, tempi e trigger diversi. Ad esempio, ha poco senso convalidare un campo prima che l'intero record sia in uno stato coerente, a meno che non si desideri convalidare un solo pezzo. I vincoli a livello di database devono essere applicabili solo alla fine prima di un commit e non possono essere prontamente eseguiti a pezzo.

Un concetto correlato è che la rappresentazione dei dati varia tra ciascuno dei livelli. Un semplice esempio è che un browser Web rappresenta un pezzo di testo come, forse, CP1290, mentre il database lo rappresenta in UTF-8; le lunghezze delle due stringhe differiscono, quindi imporre vincoli di lunghezza diventa imbarazzante.


sì, diverse lingue e framework rendono ciò poco pratico. Non "annullabile" perché con abbastanza risorse si potrebbe fare, ma scrivere convertitori automatici in e tra le lingue è un compito ENORME. Farlo in un lasso di tempo ragionevole e mantenerlo quando cambiano le tecnologie pertinenti richiederebbe molto lavoro.
Michael Durrant,

È sicuramente vero che molte validazioni lato server (ad es. Unicità di un campo) non possono essere eseguite nel browser. Tuttavia, è anche vero che tutte le convalide sul lato client devono essere ripetute nel server, poiché non è possibile fidarsi del client. È lì che vedo le cose ASCIUGARE particolarmente utili. Ad esempio, ho potuto vedere una gemma che estende Rails form_forper fornire automaticamente un codice di convalida sul lato client molto utile.
Dan

5

Una considerazione che spesso limita le soluzioni è il round trip di rete. Il client dovrebbe convalidare i dati dell'utente senza inviare un messaggio sulla rete. In altre parole, quando l'utente preme il pulsante di invio, il client dovrebbe convalidare i dati localmente.

Innanzitutto, supponiamo che non abbiamo questa limitazione. Potremmo comunicare con un endpoint di rete in grado di articolare problemi di convalida. Ad esempio, quando si inoltra il nuovo record utente, anziché rispondere con un codice di errore HTTP vanilla, potrebbe restituire una risposta JSON dettagliata che dettaglia i problemi e il client aggiorna in modo intelligente il display per riflettere i problemi riscontrati. L'endpoint svolge il ruolo di gateway di convalida.

È ASCIUTTO ma non senza inconvenienti. Innanzitutto, dipende dal round trip della rete che tassa il nostro server con convalide che avrebbero potuto essere gestite lato client. In secondo luogo, il design prevede che tutte le operazioni CRUD avverranno tramite i nostri endpoint, ma che dire di quando sviluppatori e processi ignorano il nostro livello di accesso ai dati andando direttamente contro il database ?

Rivisitiamo la nostra soluzione per superare questi inconvenienti. Invece archiviamo e comunichiamo le nostre validazioni come metadati:

{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']}

Sia il client che il server avrebbero un meccanismo (ad esempio un motore) per l'interpretazione e l'applicazione di questi dati. (Alcuni chiamano questa monade libera in quanto separa la parte dichiarativa dal suo interprete.) In JavaScript abbiamo potuto mappare ogni informazione con funzioni funzionanti. Per l'avvio, possiamo insegnare a qualsiasi livello della nostra architettura, incluso il nostro database, per applicare coerentemente le convalide.


Come descrivi un campo quando un campo è rappresentato in modo diverso nel browser web, nel trasporto, nella lingua di implementazione e nel database? Ad esempio, il numero di byte richiesti per rappresentare un campo stringa varia quando si utilizza CP1290 (IE), UTF-8 (JSON), UTF-8 (C #) o UCS-16 (Oracle). Cosa significa un vincolo di lunghezza? Ancora più importante per il browser, quando la rappresentazione del personaggio dipende dal browser e dal sistema operativo?
BobDalgleish,

Questi vincoli sono rivolti come modello mentale agli esseri umani. Il tuo lavoro come programmatore è quello di sottrarre le differenze alla macchina in modo che la persona non debba preoccuparsi di differenze tecniche.
Mario T. Lanza,

Hai completamente perso il punto. Finora nessuno ha presentato un'astrazione che consenta la validazione da un capo all'altro, con una specifica. Dal PO "scrivere una volta" implica che non si qualificano clausole diverse che affrontano fasi diverse. Allo stesso modo, nella convalida proposta non vedo nulla che affronti la convalida tra campi o tra oggetti.
BobDalgleish,

Le validazioni tra campi / oggetti non sono molto estese. I metadati rappresentano solo la relazione. Scrivi una volta implica che io scrivo una sola convalida una volta e la faccio applicare in più siti, cosa che succede. Aggiungi metadati a una tabella. I metadati vengono ricevuti da qualsiasi sito e una semplice classe / utility / motore applica il vincolo.
Mario T. Lanza,

1
Un tale linguaggio di validazione sarebbe estremamente utile. Potrebbe sostituire forse un terzo del codice coinvolto con applicazioni Web ad alta intensità di interfaccia utente.
BobDalgleish,

2

Un modo sarebbe usare la stessa lingua / framework sia sul lato server che sul lato client.

Per esempio

Node.js :: Client / Server in JavaScript GET :: Client / Server in Java

In questo caso, la maggior parte del codice "Oggetto dominio" sarebbe comune, includendo la convalida. Framework invocherà il codice come richiesto. Ad esempio, lo stesso codice verrebbe richiamato nel browser prima di "inviare" e sul servizio Web lato server.

EDIT (giugno / 2014): con Java 8, ora è facile integrare anche il codice di convalida JS nelle applicazioni Java. Java 8 ha un nuovo motore di esecuzione JS più permanente (ad esempio: utilizza invokeDynamic).


Quando si tratta del database SQL, non sono sicuro di come funzioni.
Michael Durrant,

Inoltre, non risolve il problema che il browser e il sistema operativo influiscono sul dominio di input.
BobDalgleish,

@Micheal Durrant, per la convalida del database sono implementati come vincoli DB (come chiave esterna, univoco ecc.). BobDalgleish, 1. Il problema della compatibilità browser / sistema operativo può essere mitigato utilizzando una libreria che ottimizza il tempo di esecuzione in base al browser (come Sencha) 2. La compatibilità del browser non influisce su parti "logiche" del codice come la convalida, i problemi di compatibilità sono di solito sul rendering DOM / UI.
Shamit Verma,

0

Stavo solo pensando allo stesso problema. Stavo pensando di usare ANTLR per ottenere un albero di sintassi astratto in C # e javascript. Da lì si utilizzano i camminatori di alberi per applicare le azioni specificate nella lingua agli oggetti da convalidare.

Quindi puoi archiviare una descrizione della convalida richiesta dove vuoi, possibilmente nel database.

Ecco come affronterei il problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.