Que faire lorsque vous ne pouvez pas déterminer une valeur booléenne?

38

Nous construisons une application Web pour entreprise, dont l'administration n'existait jusqu'à présent que dans des feuilles Excel. Nous avons presque terminé, mais récemment, on m'a chargé d'importer toutes les données de ces feuilles dans notre nouveau système. Le système est construit en Java, mais comme cette importation n'est qu'une opération ponctuelle, j'ai décidé d'écrire les scripts en Python à la place et de l'importer directement à l'aide de requêtes SQL. Voici le problème. Les nouveaux modèles de données contiennent de nouveaux attributs, qui ne sont pas inclus dans leurs données existantes. Dans la plupart des cas, ce n'est pas un problème, je mets juste un null où je ne peux pas trouver l'information. Mais ensuite, j'ai rencontré quelques attributs, qui sont des booléens et ne peuvent pas être NULL par défaut. J'ai d'abord essayé d'autoriser l'utilisation de null pour ces champs dans notre base de données, mais mon développeur principal m'a dit de ne pas le faire, car cela causerait des problèmes dans notre système à l'avenir. Et maintenant, je ne sais pas trop quoi faire. La solution évidente consiste à définir par défaut chaque valeur booléenne inconnue sur false, mais je pense que cela est également faux, car je ne sais pas si c'est faux.

Exemple: Supposons que vous avez une entité Car qui a un paramètre hasRadio. Vous devez maintenant importer des données dans ce modèle de données, mais dans les données, il n'y a que les colonnes "Modèle" et "Couleur", rien ne dit qu'il y ait ou non radio. Que mettez-vous dans une colonne "hasRadio" si elle ne peut pas être nulle par définition?

Quelle est la meilleure approche dans cette situation? Devrions-nous simplement dire à l'entreprise de remplir manuellement les données manquantes? Ou par défaut à faux?

Liberul
la source
70
Pour moi, autoriser NULL serait la bonne solution. Votre senior était-il plus spécifique que "causer un problème dans notre système à l'avenir"? Sinon, demandez-lui des raisons plus spécifiques.
larsbe
48
Vous devriez le changer par défaut FileNotFound, évidemment.
Vous
7
Serait-il possible d' ajouter un champ booléen, "isValidHasRadio" ou quelque chose du genre, ou est-ce que cela ferait trop de dégâts?
Hyde
9
La solution correcte consiste à considérer le déchet de données en entrée et à abandonner la totalité de la transaction, puis à exiger que la définition de la tâche soit ajustée si ces données ne doivent pas être considérées comme un déchet. Il n'y a pas d'autre moyen ici.
Sarge Borsch
17
À propos, je ne suis pas un grand fan des valeurs nulles. Je préférerais utiliser une énumération avec "Unknown", "Has Radio" et "Don't Radio". De cette façon, vous êtes couvert par vos besoins et vous avez de la place pour évoluer si vous devez spécifier un type de radio à l'avenir, tel que "Radio avec télévision intégrée" ou quelque chose du genre.
Machado

Réponses:

129

Il s’agit principalement d’un problème d’analyse des exigences, et cela n’a rien à voir avec le fait que les données en jeu sont "booléennes". Si vous devez initialiser des tables dans une base de données ou dans un autre type de stockage de données et que vous avez des entrées incomplètes pour certaines colonnes, vous devez d'abord rechercher ce que les utilisateurs du système ou votre client pensent être la bonne valeur par défaut. pour ces colonnes, et vous devez le trouver pour chaque attribut , il n'y a pas de réponse généralement correcte.

Cela conduira généralement à l'un des cas suivants:

  • il y a une bonne valeur par défaut pour la colonne spécifique, les utilisateurs ne s'inquiètent pas de savoir si la valeur est initialement la même pour tous les enregistrements, ils peuvent définir les valeurs correctes facilement par la suite si nécessaire

  • il y a une règle pour déterminer la valeur par défaut idéale à partir d'autres informations, de sorte que vous puissiez mettre cette règle dans le code

  • les utilisateurs ou votre client vont étendre les données d'entrée et fournir les valeurs manquantes (peut-être manuellement), avant qu'elles ne soient importées dans la base de données

  • il n'y a pas de bonne valeur par défaut pour la colonne spécifique et / ou pour un enregistrement, les données doivent être importées non plus, mais les utilisateurs veulent savoir pour quels enregistrements la valeur particulière est déjà initialisée et pour laquelle pas. Ils peuvent donc entrer la valeur après , et de suivre pour qui enregistre la valeur est déjà réglée correctement et pour lesquels non.

Le dernier cas nécessite quelque chose comme NULL pour représenter l'état non initialisé ou inconnu, même pour une valeur booléenne, si votre aîné l'aime ou non. S'il existe une raison technique obscure qui interdit l'utilisation d'une valeur NULL pour une colonne spécifique, vous devez simuler l'état "inconnu" d'une manière différente, en introduisant une colonne booléenne supplémentaire (du type hasRadioIsUnknown) ou en utilisant un paramètre 3. énumération -Évaluées au lieu d'un booléen (comme HasNoRadio=0, HasRadio=1, Unknown=2). Mais adressez-vous à votre supérieur, une fois que vous avez effectué une analyse approfondie des besoins, pour vous assurer qu’une telle solution de contournement est vraiment nécessaire.

Doc Brown
la source
29
Vous devez également noter que la même réponse s'applique aux autres colonnes où vous avez commodément utilisé NULL. Vous devez vérifier s'il s'agit de la valeur par défaut correcte. Si, par exemple, une autre colonne indique "processingIsFinished" et que vous importez d'anciennes données de l'historique des commandes des clients (en pensant à une boutique en ligne), vous devrez peut-être définir la valeur sur "true" plutôt que sur "NULL" pour éviter le déclenchement de certains processus. quand ils rencontrent des entrées non encore traitées (selon leur interprétation de cette colonne).
Frank Hopkins
1
C'est un problème fonctionnel. En raison du fait que les modèles (excel et le nouveau) ne correspondent pas, le processus de migration doit être examiné en tenant compte de ces cas. Le seul qui puisse dire comment procéder est / sont les parties prenantes (client ou quiconque). Techniquement, vous pouvez résoudre ce problème de nombreuses manières, mais fonctionnellement dans un seul cas. La droite.
Laiv
12
J'aime cette ventilation. Mon dégoût pour null dans ce contexte est principalement dû à son manque de sens clair. Inconnu est clair. Mais null signifie-t-il inconnu ou non applicable? Comment pourrait-on savoir? Ce n’est pas parce que cela a du sens pour vous que tout le monde le verra de la même façon.
candied_orange
Option 4: Les enregistrements manquants d'une valeur de colonne particulière sont en réalité inutiles et doivent être exclus de l'importation. Option 5: Une personne doit corriger toutes les données entrantes avant leur importation. Beaucoup d'options, cela dépend des besoins et des budgets. Importer de vieilles données est toujours un désordre énorme.
jpmc26
@ jpmc26: eh bien, je n'ai pas inclus l'option 4 car je voulais coller ce que l'OP écrivait littéralement (un cas où les données manquantes ne sont définitivement pas incluses dans les données d'importation, sans enregistrement). L’option 5 mérite en effet d’être mentionnée, car c’est un autre moyen d’éviter la nécessité des valeurs NULL. Edité ma réponse en conséquence.
Doc Brown
39

Ce n'est pas une question technique; c'est une question de règles commerciales. Donc, vous devez demander "l'entreprise".

Adressez-vous au propriétaire du produit et / ou au (x) partenaire (s) et dites quelque chose comme:

Nous avons des données incomplètes pour l'un des champs que vous avez demandé dans l'application. Voulez-vous que nous utilisions une valeur par défaut? Voulez-vous que nous ajoutions "inconnu" comme valeur valide? Ou souhaitez-vous qu'un membre de votre équipe corrige les données avant l'importation?

Une discussion s'ensuivra probablement. Mais, c'est fondamentalement ça. La solution technique découlera naturellement de règles de gestion plus étoffées.

svidgen
la source
9

Le problème général est toute une sous-zone de programmation appelée nettoyage des données, qui fait partie d'une plus grande sous-zone appelée intégration de données . Éviter ce genre de problèmes est probablement une des raisons principales de la migration des feuilles Excel et des raisons pour lesquelles le développeur senior ne veut pas laisser un champ devenir nul. Je ne pense pas qu'il soit déraisonnable de dire que c'est l'une des plus grandes sources de complexité des migrations de données.

Le simple fait d'utiliser NULL chaque fois que vous le pouvez est probablement une mauvaise chose à faire, sans parler de changer le modèle de données pour rendre encore plus de champs nuls. La vérification de l’intégrité d’Excel est faible ou inexistante, ce qui est probablement à l’origine de bon nombre de ces problèmes. La mauvaise chose à faire est de supprimer la vérification d'intégrité dans la nouvelle base de données et d'y déposer des déchets. Cela ne fait que perpétuer le problème et ajoute une complexité considérable aux intégrations futures, qui devront en quelque sorte traiter des données insensées.

Une partie de la différence est probablement due à l'inadéquation du modèle de données. Il s’agit en grande partie de connaître (intimement) les deux modèles de données et de savoir comment mapper l’ancien avec le nouveau. Tant que le nouveau est capable de capturer l'ancien. (Sinon, votre équipe a probablement un très gros problème.) Cela peut facilement nécessiter plus de travail que la simple copie de colonnes. Darkwing en donne un excellent exemple (ainsi que la raison pour laquelle insérer aveuglément des NULL est une mauvaise chose à faire). Si l’ancien modèle a un ReceivedDateet un InProgresspeu et que le nouveau modèle a un StartDateet ProcessingEndTime, vous devrez décider si et comment définir le fichier ProcessingEndTime. En fonction de la manière dont il est utilisé, un choix raisonnable (mais arbitraire) peut être de le régler de la même manière que leStartDate (ou peu de temps après si cela pose problème).

Cependant, une partie de la différence est probablement due à des données qui "devraient" être manquantes ou corrompues. (Probablement d'erreurs de saisie de données, de migrations antérieures ou de bogues dans les systèmes de traitement de données.) Si personne dans votre équipe ne s'y attendait, alors vous vous êtes (ensemble) engagé à consacrer 20% de votre temps au projet " presque fini. (C'était un numéro inventé, mais ça peut être loinpire que cela, ou mieux. Cela dépend de la quantité de données incorrectes, de son importance, de sa complexité, de la facilité avec laquelle les responsables des données peuvent intervenir, et d'autres facteurs.) Une fois que vous avez déterminé que les données sont "supposées être "là mais manque. Généralement, vous essayez de déterminer l'étendue du problème en interrogeant les anciennes sources de données. S'il s'agit de dizaines ou de centaines d'entrées, il s'agit probablement d'erreurs de saisie de données et les clients responsables des données doivent les résoudre manuellement (c'est-à-dire vous indiquer quelles valeurs doivent être.) S'il s'agit de millions d'entrées (ou d'une fraction significative des données) , alors vous devrez peut-être reconsidérer si vous avez correctement identifié qu'il "devrait être" là. Cela pourrait indiquer une erreur de modélisation dans le nouveau système.

Par exemple, imaginons une facture comportant des quantités et des totaux par article (mais pas le prix unitaire), sauf que certaines des quantités manquaient inexplicablement. Parler à la personne qui traite de telles factures peut produire un (ou plusieurs) des scénarios suivants: 1) "oh, une quantité en blanc signifie une quantité de 1", 2) "oh, je sais que ces articles coûtent environ 1 000 $ alors, il s'agit clairement d'un ordre pour 2 ", 3)" quand cela se produit, je recherche le prix dans cet autre système et divise et arrondit ", 4)" je le recherche dans un autre système ", 5)" il ne s'agit pas de données réelles ", 6)" jamais vu ça avant ".

Comme suggéré, cela peut indiquer certaines manières de résoudre automatiquement la situation, mais vous devez faire attention à ce que la solution s'applique à tous les cas. Il est fréquent que d’autres systèmes impliqués puissent recouper les données et c’est une bonne chose. Cependant, c’est souvent une mauvaise chose dans la mesure où il peut être difficile d’avoir accès à ces systèmes et de s’intégrer à ceux-ci pour effectuer la vérification croisée, et il est souvent évident que les systèmes entrent en conflit les uns avec les autres, pas seulement par manque de données. Certaines interventions manuelles sont souvent nécessaires et, en fonction de l’échelle, peuvent nécessiter un outillage et la création d’interfaces spécifiques à la tâche de nettoyage des données. Ce qui est souvent fait, c'est que les données sont partiellement importées, mais les lignes contenant des données manquantes sont envoyées dans une table séparée où elles peuvent être révisées.

Derek Elkins
la source
14
En résumé: si vous pensez que traiter avec du code hérité est désagréable, essayez de traiter avec des données héritées.
Peter Taylor
0

Changer le modèle de données.

Vous pouvez normaliser la hasradio et vous n'aurez plus de NULL.

Si vous ne pouvez pas déterminer une valeur booléenne, n'utilisez pas de booléen.

En permettant à une valeur booléenne de devenir nulle, il cesse d'être un booléen. Un booléen peut avoir 2 états: False, True.

Vous avez besoin de 3 états: False, True, Unknown.

Avez-vous la possibilité de changer le modèle de données?

(Et une autre chose à laquelle j'ai pensé, si en python ou java vous récupérez les données de votre base de données. Vous récupérez l'enregistrement, vérifiez le champ hasradio, que se passera-t-il si vous vérifiez si c'est vrai ou faux et s'il est nul?)

Pieter B
la source
2
En changeant le modèle de données et « normalisant sur hasRadio », je suppose que vous voulez dire quelque chose comme l' ajout d' une nouvelle table CarFeatures, avec des champs Car_ID, Feature_ID, Has_Feature? Cela semble être une bonne idée.
Jpa
2
@ jpa c'est un peu une situation délicate. Vous devez être très clair dans ce que vous faites, car l'absence de record dans notre cas signifie inconnu. Bien que souvent l'absence d'un disque signifie qu'il n'a pas la fonctionnalité.
Pieter B
1
Vous le regardez mal, Pieter. Personne ne dit que boola a plus de deux valeurs, parce que, comme vous l'avez dit, ce n'est pas le cas. A boolest soit trueou false. Cependant, dans le cas des OP, OP ne traite pas booldirectement, mais Option<bool>/Maybe<bool>peut avoir Some -> true/falseou None.
Andy
@DavidPacker Mon argument est que, pour cette raison, il est peut-être préférable de cesser de l'appeler de manière similaire, sinon vous risquez de créer une confusion. Et si vous insistez pour utiliser un booléen, trouvez un moyen sûr de le faire.
Pieter B
4
À mon avis, un booléen nullable convient parfaitement. Je n'ai jamais eu de problèmes avec les valeurs NULL, même si j'ai rencontré des développeurs qui l'ont fait.
Andy
-1

Comme d'autres l'ont fait remarquer, vous avez ici une valeur booléenne qui n'est pas vraiment booléenne et le problème est de le forcer à être booléen ou de le gérer autrement.

Au lieu d'avoir un seul résultat booléen, vous pouvez obtenir deux résultats booléens. Ceux-ci pourraient soit d'accord ou pas d'accord. S'ils sont d'accord, vous obtenez un résultat vrai / faux simple.

Si, toutefois, ils sont en désaccord, vous obtenez un résultat indéterminé et vous avez une chance, en fonction des circonstances dans lesquelles il se produit, de décider de la manière de le gérer. Dans certains cas, un résultat indéterminé pourrait être mieux interprété comme vrai, alors que dans d'autres, le même résultat indéterminé pourrait être interprété comme faux, selon l'option la plus sûre.

Cela permettrait néanmoins de signaler le résultat comme indéterminé, de sorte que cette nuance supplémentaire de la valeur ne soit pas complètement perdue, jusqu'au point où la valeur peut être résolue et réinitialisée de manière définitive.

Lee Leon
la source