web-dev-qa-db-fra.com

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

Nous construisons une application Web pour l'entreprise, dont l'administration n'existait jusqu'à présent que dans les feuilles Excel. Nous avons presque terminé maintenant, mais récemment, j'ai eu la tâche d'importer toutes leurs données de ces feuilles vers notre nouveau système. Le système est construit en Java, mais comme cette importation n'est qu'une seule fois, j'ai décidé d'écrire les scripts en Python à la place et de l'importer directement avec les requêtes SQL. Voici le problème. Le nouveau les 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 simplement une valeur nulle là où je ne trouve pas les informations. Mais j'ai ensuite rencontré quelques attributs , qui sont des booléens et ne peuvent pas être NULL par défaut. J'ai d'abord essayé d'autoriser simplement 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 est de faire par défaut chaque valeur booléenne inconnue à false, mais je pense que c'est faux aussi, parce que je ne sais pas vraiment, si c'est faux.

Exemple: Disons 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 sur le fait d'avoir ou non la radio. Que mettez-vous dans une colonne "hasRadio", si elle ne peut pas être nulle par conception?

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

38
Liberul

Il s'agit principalement d'un problème d'analyse des besoins, 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 tout autre type de stockage de données et que vous avez des entrées incomplètes pour certaines colonnes, vous devez d'abord déterminer 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 découvrir pour chaque attribut unique, il y a pas généralement réponse 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 se soucient pas si la valeur est initialement la même pour tous les enregistrements, ils peuvent définir les valeurs correctes facilement après si nécessaire

  • il existe une règle pour déterminer la valeur par défaut idéale à partir d'autres informations, vous pouvez donc mettre cette règle en code

  • les utilisateurs ou votre client étendront les données d'entrée et fourniront les valeurs manquantes (peut-être manuellement), avant leur importation dans la base de données

  • il n'y a pas de bonne valeur par défaut pour la colonne spécifique et/ou tout enregistrement, les données doivent être importées non plus, mais les utilisateurs veulent savoir pour lequel des enregistrements la valeur particulière est déjà initialisée et pour laquelle ne pas. Ainsi, ils peuvent entrer la valeur après, et suivre pour quels enregistrements la valeur est déjà correctement définie et pour laquelle pas.

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 senior 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, soit en introduisant une colonne booléenne supplémentaire (comme hasRadioIsUnknown) , ou en utilisant une énumération à 3 valeurs au lieu d'un booléen (comme HasNoRadio=0, HasRadio=1, Unknown=2). Mais parlez à nouveau à votre supérieur, après avoir effectué une analyse approfondie des exigences, pour vous assurer qu'une telle solution de contournement est vraiment nécessaire.

129
Doc Brown

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

Contactez le propriétaire du produit et/ou les parties prenantes et dites quelque chose comme:

Nous avons des données incomplètes pour l'un des champs que vous avez demandés dans la candidature. Souhaitez-vous que nous utilisions une valeur par défaut? Souhaitez-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 en gros ça. La solution technique découlera naturellement des règles métier plus étoffées.

39
svidgen

Le problème général est une sous-zone entière de programmation appelée nettoyage des données qui fait partie d'une sous-zone plus grande appelée intégration des données . Éviter ces types de problèmes est probablement une grande partie de la raison de la migration à partir des feuilles Excel et pourquoi le développeur senior ne veut pas autoriser 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é dans les migrations de données.

Le simple fait d'utiliser NULL chaque fois que vous le pouvez est probablement la chose incorrecte à faire, sans parler de changer le modèle de données pour rendre encore plus de champs annulables. Excel a une vérification d'intégrité faible ou nulle, ce qui est probablement la cause 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 de vider les ordures. Cela ne fait que perpétuer le problème et ajoute une complexité importante aux futures intégrations qui doivent en quelque sorte traiter des données absurdes.

Une partie de la différence est probablement due à l'inadéquation du modèle de données. Pour y faire face, il s'agit en grande partie de se familiariser (intimement) avec les deux modèles de données et de savoir comment mapper l'ancien au 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 l'insertion aveugle de NULL n'est pas la bonne chose à faire). En y réfléchissant, si l'ancien modèle avait un ReceivedDate et un bit InProgress et que le nouveau modèle avait un StartDate et ProcessingEndTime, vous devrez décider si et comment définir le ProcessingEndTime. Selon la façon dont il est utilisé, un choix raisonnable (mais arbitraire) peut être de le définir comme le StartDate (ou peu de temps après si cela pourrait causer des problèmes).

Cependant, une partie de la différence est probablement due à des données qui "devraient" être manquantes ou corrompues. (Très probablement à cause d'erreurs de saisie de données ou de migrations passées ou de bogues mal gérés dans les systèmes de traitement des données.) Si aucun membre de votre équipe ne s'y attendait, alors (collectivement), vous vous êtes mis à consacrer 20% du temps du projet à être " presque fini. (C'était un nombre composé, mais il peut être bien pire que cela, ou mieux. Cela dépend de la quantité de données incorrectes, de l'importance c'est à quel point c'est complexe, à quel point il est facile d'obtenir la participation des responsables des données, et d'autres facteurs.) Une fois que vous avez déterminé que les données sont "supposées être" là mais manquantes. Habituellement, vous tenterez 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 devraient les résoudre manuellement (c'est-à-dire vous dire quelles devraient être les valeurs). S'il s'agit de millions d'entrées (ou d'une fraction importante des données) , vous devrez peut-être reconsidérer si vous avez correctement identifié qu'il "devrait être" là. Cela peut indiquer une erreur de modélisation dans le nouveau système. Lorsque vous interrogez les personnes qui utilisent les données sur les données manquantes, elles en sont souvent quelque peu conscientes et disposent de moyens ad hoc pour y faire face.

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

Comme suggéré, cela peut indiquer certains moyens de résoudre automatiquement la situation, mais vous devez faire attention à ce que la solution s'applique à tous les cas. Il est courant que d'autres systèmes soient impliqués qui peuvent 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'accéder à ces systèmes et de s'intégrer à ces systèmes pour effectuer la vérification croisée, et il apparaît souvent que les systèmes entrent en conflit les uns avec les autres, pas seulement par le manque de données. Certaines interventions manuelles sont souvent nécessaires et, selon l'échelle, peuvent nécessiter la création d'outils et d'interfaces spécifiquement pour la tâche de nettoyage des données. Souvent, ce qui est 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 distincte où elles peuvent être consultées. Souvent, cela devra être fait avec une granularité appropriée pour assurer la cohérence dans le nouveau système (c'est-à-dire rejeter les factures et non les éléments de ligne individuels même si la plupart des éléments de ligne sont corrects dans une facture particulière) et cela peut conduire à des cascades (si je peux '' t importer un client, je ne peux pas importer de factures pour ce client).

9

Modifiez 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 de valeur booléenne, n'utilisez pas de valeur booléenne.

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

Ce dont vous avez besoin est de 3 états: Faux, Vrai, Inconnu.

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

(Et une autre chose à laquelle j'ai pensé, si dans 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, ce que se passera-t-il si vous vérifiez si c'est vrai ou faux et qu'il se trouve être nul?)

0
Pieter B