Ha senso convalidare i dati estratti dal database?

2

Questa è intesa come una domanda indipendente dalla lingua generale. È scritto intorno a un esempio strano semplicemente perché non sono riuscito a trovare un modo migliore per chiedere. Inoltre, gli "pseudocod" forniti sembrano un misto di Java e JavaScript solo perché sono le lingue con cui ho più familiarità, ma speriamo che siano facili da capire per tutti.

Diciamo che ho un campo String chiamato tuples in un database. Quando l'utente fa clic su un pulsante (il pulsante Store Numbers ), viene eseguita la funzione store_numbers , come segue (in pseudocodice):

function store_numbers() {
    // Make a bunch of calculations and generate some integer tuples,
    //     such as (0,1), (4,4) and (-500,0)
    // Create a string with those tuples, semicolon-separated,
    //     with the exact format above, such as
    //     "(0,1);(4,4);(-500,0)"
    // Insert this string in the 'tuples' field of the database (for the given UserID)
}

E questo è l'unico modo, nell'intero software, di modificare il campo tuples del database (almeno nella versione attuale del software).

Ora diciamo che lo stesso utente ritorna domani e fa clic su un altro pulsante (il pulsante Calcola elementi ) e viene eseguita la funzione calculate_stuff . Questa funzione leggerà la stringa tuples dal database e dovrebbe eseguire vari calcoli con le tuple. DOMANDA : posso supporre che la stringa tuples sia formattata perfettamente? O dovrei prima convalidare la stringa proveniente dal database?

OPZIONE 1: Supponendo che sia perfettamente formattato:

function calculate_stuff() {
    String tuples = // read string from database...
    // immediately begin calculations assuming string is perfect
    for (String tuple in tuples.split(';')) {
        String[] temp = tuple.replace('(','').replace(')','').split(',');
        int x = Math.parseInt(temp[0]);
        int y = Math.parseInt(temp[1]);
        // ...
    }
    // ...

    // If somehow the string was wrong, ugly errors will be thrown,
    //     and the software will crash.
    // But this shouldn't happen, since the string was crafted
    //     correctly in the store_numbers() function.
}

OPZIONE 2: Convalida prima:

function calculate_stuff() {
    String tuples = // read string from database...

    // Check if the string is OK first:
    if (!is_a_semicolon_separated_list_of_integer_tuples(tuples)) {
        error("Oh no! Something terrible happened! How come??");
    } else {
        // Proceed calculations...
    }
}

I MIEI PENSIERI: l'opzione 1 non darà alcun messaggio di errore decente all'utente - il software si bloccherà invece. Questo è terrificante in una prospettiva UX, ma poiché la stringa è stata creata correttamente dall'altra funzione, questo non dovrebbe mai accadere . D'altra parte, forse non fa male aggiungere l'assegno? Bene ... Codificare il is_a_semicolon_separated_list_of_integer_tuples non è così difficile , ma neanche ridicolmente facile. E se fosse una stringa molto più complicata, la cui convalida richiederebbe centinaia di righe di codice ?? Per qualcosa che non accadrà mai?

Quali sono le linee guida per questo? Quali sono le buone pratiche di programmazione in questione?

    
posta Pedro A 27.07.2016 - 23:54
fonte

3 risposte

6

La domanda essenziale è quanto bene puoi controllare chi può modificare i dati all'interno del database.

La maggior parte dei database consente di definire i vincoli per le diverse colonne. Nel tuo caso, ¹ puoi impostare una regola che impone il formato tupla specifico, quindi (0,1) sarebbe valido, mentre (0, 1) o (0:1) non lo sarebbero. Ciò garantisce che i dati utilizzino necessariamente il formato richiesto, il che rende meno importante avere i controlli aggiuntivi all'interno dell'applicazione se si ha fiducia nello schema del database (e si sa che qualcuno non lo cambierà senza rieseguire i test della propria app) .

Se il formato non viene applicato attraverso lo schema, in genere2 i dati non validi vengono trovati prima o poi nel database per cercare te e le tue applicazioni. Questi dati potrebbero venire:

  • Dalla tua applicazione. Cambiamenti di codice. Gli sviluppatori potrebbero non essere consapevoli dei formati che avrebbero dovuto essere utilizzati. Oppure potrebbero essere consapevoli, ma fare un errore. Poiché il formato non è applicato, gli errori sono molto difficili da individuare.

  • Da altre applicazioni. Diverse applicazioni di diversi team possono accedere allo stesso database e, data la mancanza di regole correttamente applicate, anche una documentazione chiara non aiuta necessariamente.

  • dai comandi eseguiti manualmente. Qualcuno, da qualche parte, aveva bisogno di inserire un valore mancante, seguendo un bug ad alta priorità, e non era a conoscenza del formato da usare, o, ancora una volta, ha fatto un refuso.

Quando codifica in modo difensivo , un approccio popolare è quello di fare una separazione tra l'applicazione stessa, ritenuta affidabile e l'esterno mondo di cui non ci si deve fidare.

Questo potrebbe applicarsi a molti livelli: chiamate dai client REST rispetto al servizio web stesso; file system e codice dell'applicazione; quadro contro applicazione; classe contro metodo. Se sviluppi una singola classe, altre classi possono essere considerate come un mondo esterno (questo, ad esempio, porta a campi che vengono sostituiti da proprietà o a principio aperto / chiuso ). Per un metodo all'interno di una classe, altri metodi possono essere considerati come un mondo esterno.

Nel tuo caso, la domanda è se dovessi considerare il tuo database come un mondo esterno. A volte dovresti. In altri casi, non è necessario, e ulteriori verifiche dei dati a livello di applicazione non apporterebbero troppi vantaggi, pur richiedendo troppo tempo per sviluppare e mantenere tali controlli.

Immagina di sviluppare un videogioco proprietario. La licenza proibisce esplicitamente qualsiasi modifica al database sottostante e il database stesso è crittografato per impedire l'uso non autorizzato. Ora, un utente decide di decodificare il gioco per ottenere l'accesso al database e modifica alcuni dati al suo interno. Al prossimo avvio, il gioco fallisce, perché il formato dei dati non è valido. È davvero importante?

¹ Si noti che se si ha a che fare con RDBMS , si è dato un terribile esempio di dati formattati (suppongo che se si tratta di un database come Redis, l'esempio sarebbe valido , anche se non conosco abbastanza bene i Redis). In un database relazionale, invece di memorizzare tuple in questo modo, è necessario memorizzare singoli valori. Ciò quindi renderebbe la convalida come specificato (per lo più) irrilevante.

² Oppure, secondo la mia esperienza personale, in ogni singolo caso .

    
risposta data 28.07.2016 - 00:11
fonte
3

Prova a cercare questo non dovrebbe mai accadere su github. Al momento della stesura di questo articolo, le persone hanno pianificato per quell'eventualità 18.210.436 volte. Perché? Perché se dovesse mai accadere e non ci si è preparati registrando un messaggio di errore corretto, sarà davvero folle da rintracciare. Non penserai mai di guardare lì finché non sarai abbastanza pazzo da rivedere il tuo tavolo manualmente riga per riga. O peggio, la tabella del tuo cliente importante riga per riga perché non puoi riprodurla localmente. Non ti costa praticamente nulla per convalidarlo su entrambe le estremità ora.

Sono d'accordo con MainMa, però, questo è ciò a cui servono gli schemi. Memorizzali correttamente come numeri separati e eviti un sacco di problemi futuri.

    
risposta data 28.07.2016 - 01:21
fonte
1

Dipende.

Come regola aziendale, è OK se i dati non validi sono presenti nel database? Gli utenti hanno la possibilità di modificare i dati direttamente? Se inseriscono dati non validi, è necessario mantenerli e consentire loro di modificarli più tardi?

In tal caso: è necessario convalidare ogni lettura, ogni volta e determinare cosa fare con i dati in base a tale convalida, come regola aziendale.

In caso contrario: convalida solo una volta, quando i dati vanno in il database.

    
risposta data 28.07.2016 - 00:26
fonte

Leggi altre domande sui tag