Cosa fare quando non è possibile determinare un valore booleano?


38

Stiamo costruendo un'applicazione web per l'azienda, la cui amministrazione esisteva finora solo nei fogli Excel. Ormai abbiamo quasi finito, ma recentemente mi è stato assegnato un compito per importare tutti i loro dati da quei fogli nel nostro nuovo sistema. Il sistema è integrato in Java, ma poiché questa importazione è solo una volta, ho deciso di scrivere gli script in Python e importarli direttamente con query SQL. Ecco che arriva il problema. I nuovi modelli di dati contengono alcuni nuovi attributi, che non sono inclusi nei loro dati esistenti. Nella maggior parte dei casi, questo non è un problema, ho solo messo un null dove non riesco a trovare le informazioni. Ma poi ho incontrato alcuni attributi, che sono booleani e non possono essere NULL per impostazione predefinita. Per prima cosa ho provato a consentire solo null per quei campi nel nostro database, ma il mio senior dev mi ha detto di non farlo, in quanto causerebbe problemi nel nostro sistema in futuro. E ora non sono abbastanza sicuro di cosa fare. La soluzione ovvia è quella di impostare come falso ogni valore booleano sconosciuto, ma penso che sia sbagliato anche perché in realtà non so se sia falso.

Esempio: supponiamo che tu abbia un'entità Car che ha un parametro hasRadio. Ora è necessario importare i dati in questo modello di dati, ma nei dati ci sono solo le colonne "Modello" e "Colore", nulla di ciò che ha o non ha la radio. Cosa metti in una colonna "hasRadio", se non può essere nullo in base alla progettazione?

Qual è l'approccio migliore in questa situazione? Dobbiamo semplicemente dire alla società di compilare manualmente i dati mancanti? O predefinito su falso?


70
Per me consentire NULL sarebbe la soluzione corretta. Il tuo senior era più specifico di "causare un problema nel nostro sistema in futuro"? In caso contrario, chiedigli dei motivi più specifici.
Larsbe,

48
Dovresti impostarlo su FileNotFound, ovviamente.
Si

7
Sarebbe possibile aggiungere un campo booleano, "isValidHasRadio" o qualcosa del genere, o anche questo spezzerebbe le cose?
hyde,

9
La soluzione corretta è considerare l'immondizia dei dati di input e interrompere l'intera transazione, quindi richiedere che la definizione dell'attività venga modificata se tali dati non devono essere considerati immondizia. Non c'è altro modo qui.
Sarge Borsch,

17
A proposito, non sono un grande fan dei valori null. Preferirei usare un enum con 'Unknown', 'Has Radio' e 'Doesn't Have Radio'. In questo modo sei coperto dalle tue esigenze e hai spazio per crescere se devi specificare un tipo di radio in futuro, come "Radio con TV integrata" o qualcosa del genere.
Machado,

Risposte:


129

Questo è principalmente un problema di analisi dei requisiti e non ha nulla a che fare con il fatto che i dati in questione sono "booleani". Se devi inizializzare le tabelle in un database o in qualsiasi altro tipo di archiviazione dei dati e disponi di input incompleti per alcune colonne, devi prima scoprire quali utenti del sistema o il tuo cliente ritengono essere il giusto valore predefinito per quelle colonne, e devi scoprirlo per ogni singolo attributo , non esiste una risposta generalmente corretta.

Questo di solito porta a uno dei seguenti casi:

  • esiste un buon valore predefinito per la colonna specifica, agli utenti non importa se il valore è inizialmente lo stesso per tutti i record, possono impostare facilmente i valori corretti successivamente quando necessario

  • esiste una regola su come determinare il valore predefinito ideale da altre informazioni, quindi è possibile inserire questa regola nel codice

  • gli utenti o il cliente estenderanno i dati di input e forniranno i valori mancanti (forse manualmente), prima che vengano importati nel database

  • non esiste un buon valore predefinito per la colonna specifica e / o qualsiasi record, i dati devono essere importati o, ma gli utenti vogliono sapere per quale dei record il valore particolare è già inizializzato e per quale no. Quindi possono inserire il valore in un secondo momento e tracciare per quali record il valore è già impostato correttamente e per quali no.

L'ultimo caso richiede qualcosa come NULL per rappresentare lo stato non inizializzato o sconosciuto, anche per un valore booleano, se al tuo senior piace o no. Se c'è qualche oscuro motivo tecnico che vieta l'uso di un valore NULL per una colonna specifica, è necessario simulare lo stato "sconosciuto" in un modo diverso, sia introducendo una colonna booleana aggiuntiva (come hasRadioIsUnknown), sia usando un 3 enumerazione -valued invece di un valore booleano (come HasNoRadio=0, HasRadio=1, Unknown=2). Ma parla di nuovo con il tuo senior, dopo aver effettuato un'analisi approfondita dei requisiti, per assicurarti che tale soluzione alternativa sia davvero necessaria.


29
Si noti inoltre che la stessa risposta si applica alle altre colonne in cui è stato convenientemente utilizzato NULL. È necessario verificare se questo è il valore predefinito corretto. Se, ad esempio, un'altra colonna indica "processingIsFinished" e importate vecchi dati dalla cronologia degli ordini dei clienti (pensando a un negozio online), potrebbe essere necessario impostare il valore su "true" anziché "NULL" per evitare l'attivazione di alcuni processi quando incontrano voci non ancora elaborate (secondo la loro interpretazione di quella colonna).
Frank Hopkins,

1
Questo è un problema funzionale. A causa dei modelli (eccelle e quello nuovo) non corrispondenti, il processo di migrazione dovrebbe essere rivisto tenendo conto di questi casi. L'unico che può dire come procedere è / sono gli stakeholder (cliente o chiunque). Tecnicamente puoi risolverlo in molti modi, ma funzionalmente solo in uno. La destra.
Laiv

12
Mi piace questa ripartizione. Il mio disgusto per il nulla in questo contesto è principalmente dovuto alla mancanza di un chiaro significato. Lo sconosciuto è chiaro. Ma null significa sconosciuto o non applicabile? Come qualcuno lo saprebbe? Solo perché ha senso per te non significa che tutti lo vedranno allo stesso modo.
candied_orange,

Opzione 4: i record mancanti di un determinato valore di colonna sono effettivamente inutili e devono essere esclusi dall'importazione. Opzione 5: qualcuno deve correggere tutti i dati in arrivo prima che vengano importati. Molte opzioni, dipende solo da esigenze e budget. L'importazione di vecchi dati è sempre un gran casino.
jpmc26,

@ jpmc26: beh, non ho incluso l'opzione 4 poiché volevo attaccare ciò che l'OP ha letteralmente scritto (un caso in cui i dati mancanti non sono sicuramente inclusi nei dati di importazione, senza registrazione). Vale la pena menzionare l'opzione 5, poiché è un altro modo per evitare la necessità di valori NULL. Modificato la mia risposta di conseguenza.
Doc Brown,

39

Questa non è una domanda tecnica; è una domanda sulle regole aziendali. Quindi, è necessario chiedere "l'azienda".

Contattare il proprietario del prodotto e / o le parti interessate e dire qualcosa come:

Abbiamo dati incompleti per uno dei campi richiesti nella domanda. Vuoi che usiamo un valore predefinito? Vuoi che aggiungiamo "sconosciuto" come valore valido? Oppure, desideri che qualcuno nel tuo team corregga i dati prima dell'importazione?

Probabilmente seguiranno alcune discussioni. Ma è praticamente tutto. La soluzione tecnica deriverà naturalmente dalle regole aziendali più raffinate.


9

Il problema generale è un'intera sottozona di programmazione chiamata pulizia dei dati che fa parte di una sottozona più ampia chiamata integrazione dei dati . Evitare questo tipo di problemi è probabilmente una grande parte del motivo della migrazione dai fogli di Excel e perché lo sviluppatore senior non vuole consentire che un campo diventi nulla. Non credo sia irragionevole affermare che questa è una delle maggiori fonti di complessità nelle migrazioni dei dati.

Scegliere semplicemente di utilizzare NULL ogni volta che è possibile è probabilmente la cosa sbagliata , per non parlare della modifica del modello di dati per rendere ancora più nulli i campi. Excel ha un controllo di integrità debole o assente che è probabilmente la causa di molti di questi problemi. La cosa sbagliata da fare è rimuovere il controllo di integrità nel nuovo database e scaricare la spazzatura in esso. Ciò perpetua il problema e aggiunge una notevole complessità alle integrazioni future che devono in qualche modo occuparsi di dati senza senso.

Parte della differenza è probabilmente dovuta alla mancata corrispondenza del modello di dati. Affrontare questo è in gran parte una questione di familiarità (intima) con entrambi i modelli di dati e sapere come mappare quello vecchio a quello nuovo. Finché il nuovo è in grado di catturare quello vecchio. (In caso contrario, è probabile che il tuo team abbia un grosso problema.) Ciò può facilmente richiedere più lavoro rispetto alla semplice copia di colonne. Darkwing fornisce un eccellente esempio di questo (oltre al perché l'inserimento cieco di NULL è la cosa sbagliata da fare). Elaborandolo, se il vecchio modello aveva un ReceivedDatee un InProgresspo 'e il nuovo modello ha un StartDatee ProcessingEndTime, dovrai decidere se e come impostare il ProcessingEndTime. A seconda di come viene utilizzato, una scelta ragionevole (ma arbitraria) potrebbe essere quella di impostarla come la stessaStartDate (o poco dopo se ciò potrebbe causare problemi).

Tuttavia, una parte della differenza è probabilmente dovuta ai dati che "dovrebbero" essere mancanti o danneggiati. (Molto probabilmente a causa di errori di immissione dei dati o migrazioni passate o bug scarsamente gestiti nei sistemi di elaborazione dei dati.) Se nessuno nel tuo team lo ha anticipato, allora (collettivamente) ti sei impegnato a spendere il 20% del tempo del progetto " quasi fatto. (Era un numero inventato, ma può essere lontanopeggio di così, o meglio. Dipende da quanti dati non sono corretti, da quanto è importante, da quanto sia complessa, da quanto sia facile ottenere il coinvolgimento dei responsabili dei dati e da altri fattori.) Una volta stabilito che i dati "dovrebbero essere "lì ma manca. Di solito tenterai di determinare l'entità del problema interrogando le vecchie origini dati. Se si tratta di dozzine o centinaia di voci, allora probabilmente sono errori di immissione dei dati e i clienti responsabili dei dati dovrebbero risolverli manualmente (cioè dirti quali dovrebbero essere i valori.) Se sono milioni di voci (o una frazione significativa dei dati) , potrebbe essere necessario riconsiderare se hai correttamente identificato che "dovrebbe essere" lì. Ciò potrebbe indicare un errore di modellazione nel nuovo sistema.

Ad esempio, immagina una fattura con quantità e totali per articolo (ma non prezzo unitario), tranne per il fatto che alcune delle quantità erano inspiegabilmente mancanti. Parlare con la persona che elabora tali fatture potrebbe produrre uno (o più) dei seguenti scenari: 1) "oh, una quantità vuota significa una quantità di 1", 2) "oh, so che quegli articoli costano circa $ 1.000, quindi chiaramente questo è un ordine per 2 ", 3)" quando ciò accade, io cerco il prezzo in questo altro sistema e lo divido e giro ", 4)" lo cerco in un altro sistema ", 5)" non sono dati reali ", 6)" mai visto prima ".

Come suggerito, questo può indicare alcuni modi per risolvere automaticamente la situazione, ma devi stare attento che la soluzione si applichi a tutti i casi. È comune coinvolgere altri sistemi che possono effettuare controlli incrociati dei dati, e questa è una buona cosa. Tuttavia, spesso è una cosa negativa in quanto può essere difficile ottenere l'accesso e integrarsi con questi sistemi per eseguire il controllo incrociato, e spesso viene alla luce che i sistemi sono in conflitto tra loro non solo perché mancano alcuni dati. Spesso è necessario un intervento manuale e, a seconda della scala, potrebbe essere necessario creare strumenti e interfacce specificamente per l'attività di pulizia dei dati. Spesso ciò che viene fatto è che i dati vengono parzialmente importati ma le righe con dati mancanti vengono inviate a una tabella separata dove possono essere riviste.


14
In sintesi: se ritieni che gestire il codice legacy sia spiacevole, prova a gestire i dati legacy.
Peter Taylor,

0

Cambia il modello di dati.

Puoi normalizzare l'hashradio e quindi non avrai più null.

Se non riesci a determinare un valore booleano, non utilizzare un valore booleano.

Consentendo a un valore booleano di diventare nullo, smette di essere un valore booleano. Un booleano può avere 2 stati: Falso, Vero.

Ciò di cui hai bisogno sono 3 stati: falso, vero, sconosciuto.

Hai la possibilità di cambiare il modello di dati?

(E un'altra cosa a cui ho pensato, se in Python o Java recuperi i dati dal tuo database. Recuperi il record, controlli il campo hasradio, cosa succederà se controlli se è vero o falso e succede che sia nullo?)


2
Cambiando il modello di dati e "normalizzare fuori hasRadio", è qualcosa di Presumo media come l'aggiunta di una nuova tabella CarFeatures, con i campi Car_ID, Feature_ID, Has_Feature? Sembra una buona idea.
jpa,

2
@jpa è un po 'una situazione difficile. Devi essere molto chiaro in quello che fai, perché l'assenza di un record nella nostra situazione significa sconosciuto. Mentre spesso l'assenza di un record significa che non ha la funzione.
Pieter B,

1
La stai guardando male, Pieter. Nessuno dice che a boolabbia più di due valori, perché, come hai detto, non lo è. A boolè o trueo false. Tuttavia, nel caso dei PO, OP non ha a che fare booldirettamente con un , ma piuttosto con un Option<bool>/Maybe<bool>, che può avere Some -> true/falseo None.
Andy,

@DavidPacker la mia tesi è che a causa di ciò è forse un <bool> che dovresti smettere di chiamarlo come qualcosa di remoto simile o otterrai confusione. E se insisti nell'usare un booleano, trova un modo sicuro per farlo.
Pieter B,

4
Secondo me, il booleano nullable va benissimo. Non ho mai avuto problemi con valori nulli, anche se ho incontrato sviluppatori che lo hanno fatto.
Andy,

-1

Come altri hanno sottolineato, quello che hai qui è un valore booleano che non è veramente booleano e il problema è costringerlo a essere booleano o gestirlo in altro modo.

Quello che potresti fare è, invece di avere un singolo risultato booleano, avere due risultati booleani. Questi potrebbero essere d'accordo o in disaccordo. Se sono d'accordo, allora hai un risultato vero / falso.

Se, tuttavia, non sono d'accordo, allora hai un risultato indeterminato e hai la possibilità, a seconda delle circostanze in cui si presenta, di decidere come gestirlo. In alcuni casi un risultato indeterminato potrebbe essere meglio interpretato come vero, mentre in altri lo stesso risultato indeterminato potrebbe essere interpretato come falso, secondo l'opzione più sicura.

Ciò consentirebbe comunque di riportare il risultato come indeterminato, quindi questa ulteriore sfumatura del valore non andrebbe completamente persa, fino al punto in cui il valore può essere definitivamente risolto e ripristinato.

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.