¿Qué hacer cuando no puede determinar un valor booleano?

38

Estamos creando una aplicación web para la empresa, cuya administración solo existía en las hojas de Excel hasta el momento. Ya casi hemos terminado, pero recientemente me asignaron una tarea para importar todos sus datos de esas hojas a nuestro nuevo sistema. El sistema está construido en Java, pero como esta importación es solo una vez, decidí escribir los scripts en Python e importarlos directamente con consultas SQL. Aquí viene el problema. Los nuevos modelos de datos contienen algunos atributos nuevos, que no se incluyen en sus datos existentes. En la mayoría de los casos, esto no es un problema, solo pongo un nulo donde no puedo encontrar la información. Pero luego me encontré con algunos atributos, que son booleanos y no pueden ser NULL por defecto. Primero traté de permitir solo nulo para esos campos en nuestra base de datos, pero mi desarrollador principal me dijo que no lo hiciera, ya que causaría problemas en nuestro sistema en el futuro. Y ahora no estoy muy seguro de qué hacer. La solución obvia es predeterminar cada valor booleano desconocido a falso, pero creo que eso también está mal, porque en realidad no sé si es falso.

Ejemplo: supongamos que tiene una entidad Car que tiene un parámetro hasRadio. Ahora necesita importar datos a este modelo de datos, pero en los datos solo hay columnas "Modelo" y "Color", nada de que tenga o no radio. ¿Qué pones en una columna "hasRadio", si no puede ser nula por diseño?

¿Cuál es el mejor enfoque en esta situación? ¿Deberíamos decirle a la compañía que complete manualmente los datos faltantes? ¿O por defecto es falso?

Liberul
fuente
70
Para mí, permitir NULL sería la solución correcta. ¿Fue su senior más específico que "causar un problema en nuestro sistema en el futuro"? Si no, pregúntele por razones más específicas.
larsbe
48
Deberías usarlo por defecto FileNotFound, obviamente.
Usted
77
¿Sería posible agregar un campo booleano, "isValidHasRadio" o algo así, o eso también rompería las cosas?
hyde
9
La solución correcta es considerar la basura de los datos de entrada y abortar la transacción completa, y luego exigir que la definición de la tarea se ajuste si esos datos no deben considerarse basura. No hay otra manera aquí.
Sarge Borsch
17
Por cierto, no soy un gran admirador de los valores nulos. Prefiero usar una enumeración con 'Desconocido', 'Tiene radio' y 'No tiene radio'. De esta forma, estará cubierto por sus requisitos y tendrá espacio para crecer si tiene que especificar un tipo de radio en el futuro, como 'Radio con TV integrada' o algo así.
Machado

Respuestas:

129

Este es principalmente un problema de análisis de requisitos, y no tiene nada que ver con el hecho de que los datos en juego son "booleanos". Si tiene que inicializar tablas en una base de datos, o en cualquier otro tipo de almacenamiento de datos, y tiene una entrada incompleta para algunas columnas, primero debe averiguar qué piensan los usuarios del sistema o su cliente que sería el valor predeterminado correcto para esas columnas, y necesita encontrar esto para cada atributo , generalmente no hay una respuesta correcta.

Esto generalmente conducirá a uno de los siguientes casos:

  • hay un buen valor predeterminado para la columna específica, a los usuarios no les importa si el valor es inicialmente el mismo para todos los registros, luego pueden establecer los valores correctos fácilmente cuando sea necesario

  • hay una regla sobre cómo determinar el valor predeterminado ideal a partir de otra información, por lo que puede poner esta regla en código

  • los usuarios o su cliente ampliarán los datos de entrada y proporcionarán los valores faltantes (tal vez manualmente), antes de que se importen a la base de datos

  • no hay un buen valor predeterminado para la columna específica y / o cualquier registro, los datos también deben importarse, pero los usuarios desean saber para cuál de los registros el valor particular ya está inicializado y para cuál no. Para que puedan ingresar el valor después , y rastrear para qué registros el valor ya está configurado correctamente y para cuáles no.

El último caso requiere algo como NULL para representar el estado no inicializado o desconocido, incluso para un valor booleano, si a su superior le gusta o no. Si hay alguna razón técnica oscura que prohíbe el uso de un valor NULL para una columna específica, debe simular el estado "desconocido" de una manera diferente, ya sea mediante la introducción de una columna booleana adicional (como hasRadioIsUnknown), o mediante el uso de un 3 enumeración -valued en lugar de un valor booleano (como HasNoRadio=0, HasRadio=1, Unknown=2). Pero hable nuevamente con su superior, después de realizar un análisis exhaustivo de los requisitos, para asegurarse de que tal solución sea realmente necesaria.

Doc Brown
fuente
29
También debe tener en cuenta que la misma respuesta se aplica a las otras columnas donde convenientemente usó NULL. Debe verificar si este es el valor predeterminado correcto. Si, por ejemplo, alguna otra columna dice "ProcessingIsFinished" e importa datos antiguos del historial de pedidos de los clientes (pensando en una tienda web), es posible que deba establecer el valor en "verdadero" en lugar de "NULL" para evitar que se activen algunos procesos cuando encuentran entradas aún no procesadas (de acuerdo con su interpretación de esa columna).
Frank Hopkins
1
Este es un problema funcional. Debido a que los modelos (sobresale y el nuevo) no coinciden, el proceso de migración debe revisarse teniendo en cuenta estos casos. Lo único que puede decir cómo proceder es / son las partes interesadas (cliente o quien sea). Técnicamente, puede resolver esto de muchas maneras, pero funcionalmente solo en una. El derecho.
Laiv
12
Me gusta este desglose. Mi disgusto por nulo en este contexto se debe principalmente a su falta de significado claro. Desconocido es claro. ¿Pero nulo significa desconocido o no aplicable? ¿Cómo lo sabría alguien? El hecho de que tenga sentido para usted no significa que todos los demás lo vean de la misma manera.
candied_orange
Opción 4: los registros que faltan un valor de columna en particular son realmente inútiles y deben excluirse de la importación. Opción 5: alguien debe corregir todos los datos entrantes antes de que se importen. Muchas opciones, solo depende de las necesidades y presupuestos. Importar datos antiguos siempre es un gran desastre.
jpmc26
@ jpmc26: bueno, no incluí la opción 4 ya que quería pegar lo que el OP escribió literalmente (un caso en el que los datos faltantes definitivamente no se incluyen en los datos de importación, para ningún registro). Vale la pena mencionar la opción 5, ya que es otra forma de evitar la necesidad de valores NULL. Edité mi respuesta en consecuencia.
Doc Brown
39

Esta no es una pregunta técnica; Es una cuestión de reglas de negocios. Por lo tanto, debe preguntar "el negocio".

Acérquese al propietario del producto y / o partes interesadas y diga algo como:

Tenemos datos incompletos para uno de los campos que solicitó en la aplicación. ¿Desea que usemos un valor predeterminado? ¿Desea que agreguemos "desconocido" como valor válido? ¿O le gustaría que alguien de su equipo corrija los datos antes de la importación?

Alguna discusión probablemente se producirá. Pero, eso es básicamente todo. La solución técnica fluirá naturalmente a partir de las reglas de negocio más desarrolladas.

svidgen
fuente
9

El problema general es toda una subárea de programación llamada limpieza de datos que forma parte de una subárea más grande llamada integración de datos . Evitar este tipo de problemas es probablemente una gran parte de la razón de la migración desde las hojas de Excel y por qué el desarrollador principal no quiere permitir que un campo se vuelva anulable. No creo que sea irrazonable decir que esta es una de las mayores fuentes de complejidad en las migraciones de datos.

Simplemente elegir usar NULL siempre que pueda es muy probable que sea algo incorrecto , y mucho menos cambiar el modelo de datos para que aún más campos sean anulables. Excel tiene una comprobación de integridad débil o nula, que probablemente sea la causa de muchos de estos problemas. Lo incorrecto es eliminar la comprobación de integridad en la nueva base de datos y volcar basura en ella. Esto simplemente perpetúa el problema y agrega una complejidad significativa a las integraciones futuras que de alguna manera tienen que tratar con datos sin sentido.

Es probable que parte de la diferencia se deba al desajuste del modelo de datos. Tratar con esto es en gran medida una cuestión de estar (íntimamente) familiarizado con ambos modelos de datos y saber cómo asignar el antiguo al nuevo. Mientras el nuevo sea capaz de capturar al anterior. (Si no, es probable que su equipo tenga un problema muy grande). Esto puede requerir fácilmente hacer más trabajo que simplemente copiar columnas. Darkwing da un excelente ejemplo de esto (así como por qué insertar ciegamente NULL es lo incorrecto). Si lo desarrollamos, si el modelo anterior tenía un ReceivedDatey un InProgresspoco y el nuevo modelo tiene un StartDatey ProcessingEndTime, tendrá que decidir si y cómo configurarlo ProcessingEndTime. Dependiendo de cómo se use, una opción razonable (pero arbitraria) podría ser configurarlo para que sea el mismo que elStartDate (o poco después si eso causaría problemas).

Sin embargo, parte de la diferencia probablemente se deba a los datos que "deberían" estar allí que faltan o están dañados. (Lo más probable es que se deba a errores de entrada de datos o migraciones pasadas mal o errores en los sistemas de procesamiento de datos). Si nadie en su equipo lo anticipó, entonces (colectivamente) se han comprometido a pasar el 20% del tiempo del proyecto " casi termino. (Ese era un número inventado, pero puede estar lejospeor que eso, o mejor. Depende de cuántos datos sean incorrectos, cuán importantes sean, cuán complejos sean, cuán fácil sea involucrar a los responsables de los datos y otros factores). Una vez que haya determinado que los datos "deben" estar "allí pero falta. Por lo general, intentará determinar el alcance del problema consultando las fuentes de datos antiguas. Si se trata de docenas o cientos de entradas, entonces es probable que se trate de errores de entrada de datos y los clientes responsables de la información deberían resolverla manualmente (es decir, decirle cuáles deberían ser los valores). Si se trata de millones de entradas (o una fracción significativa de los datos) , entonces es posible que deba reconsiderar si identificó correctamente que "debería estar" allí. Esto podría indicar un error de modelado en el nuevo sistema.

Por ejemplo, imagine una factura que tenía cantidades y totales por artículo (pero no precio unitario), excepto que algunas de las cantidades faltaban inexplicablemente. Hablar con la persona que procesa tales facturas podría producir uno (o más) de los siguientes escenarios: 1) "oh, una cantidad en blanco significa una cantidad de 1", 2) "oh, sé que esos artículos cuestan alrededor de $ 1,000, así que, claramente este es un pedido de 2 ", 3)" cuando eso sucede, busco el precio en este otro sistema y divido y redondeo ", 4)" Lo busco en otro sistema ", 5)" eso no es información real ", 6)" nunca había visto eso antes ".

Como se sugiere, esto puede indicar algunas formas de resolver automáticamente la situación, pero debe tener cuidado de que la solución se aplique a todos los casos. Es común que otros sistemas se involucren y puedan verificar los datos, y esto es algo bueno. Sin embargo, a menudo es algo malo en la medida en que puede ser difícil obtener acceso e integrarse con estos sistemas para realizar la verificación cruzada, y a menudo sale a la luz que los sistemas entran en conflicto entre sí, no solo por la falta de algunos datos. A menudo se requiere alguna intervención manual, y dependiendo de la escala, bien puede requerir herramientas e interfaces para ser creadas específicamente para la tarea de limpieza de datos. A menudo, lo que se hace es que los datos se importan parcialmente, pero las filas con datos faltantes se envían a una tabla separada donde se pueden revisar.

Derek Elkins
fuente
14
En resumen: si cree que tratar con código heredado es desagradable, intente con datos heredados.
Peter Taylor
0

Cambiar el modelo de datos.

Puede normalizar el hasradio y ya no tendrá nulos.

Si no puede determinar un valor booleano, no use un booleano.

Al permitir que un valor booleano se vuelva nulo, deja de ser booleano. Un booleano puede tener 2 estados: falso, verdadero.

Lo que necesita son 3 estados: falso, verdadero, desconocido.

¿Tiene la opción de cambiar el modelo de datos?

(Y otra cosa en la que pensé, si en python o java recuperas los datos de tu base de datos. Recuperas el registro, verificas el campo hasradio, ¿qué sucederá si verificas si es verdadero o falso y resulta ser nulo?)

Pieter B
fuente
2
Al cambiar el modelo de datos y "normalizar cabo hasRadio", yo supongo que significar algo así como la adición de una nueva tabla CarFeatures, con los campos Car_ID, Feature_ID, Has_Feature? Parece una buena idea.
jpa
2
@jpa es una situación un poco complicada. Debe ser muy claro en lo que hace, porque la ausencia de un registro en nuestra situación significa desconocido. Si bien a menudo la ausencia de un registro significa que no tiene la función.
Pieter B
1
Lo estás mirando mal, Pieter. Nadie dice que a booltiene más de dos valores, porque, como usted ha dicho, no lo tiene. A booles cualquiera trueo false. Sin embargo, en el caso de los OP, OP no trata booldirectamente con un , sino con un Option<bool>/Maybe<bool>, que puede tener Some -> true/falseo None.
Andy
@DavidPacker mi argumento es que debido a eso es un Quizás <bool> deberías dejar de llamarlo de forma remotamente similar o obtendrás confusión. Y si insiste en usar un booleano, busque una forma segura de hacerlo.
Pieter B
44
En mi opinión, el booleano anulable está completamente bien. Nunca he tenido problemas con los valores nulos, aunque he conocido a desarrolladores que sí.
Andy
-1

Como otros han señalado, lo que tiene aquí es un valor booleano que no es realmente booleano y el problema es forzarlo a ser booleano o manejarlo de otra manera.

Lo que podría hacer es, en lugar de tener un único resultado booleano, tener dos resultados booleanos. Estos podrían estar de acuerdo o en desacuerdo. Si están de acuerdo, entonces tiene un resultado verdadero verdadero / falso.

Sin embargo, si no están de acuerdo, entonces tiene un resultado indeterminado y tiene la oportunidad, dependiendo de las circunstancias en que se presente, de decidir cómo manejarlo. En algunos casos, un resultado indeterminado puede interpretarse mejor como verdadero, mientras que en otros, el mismo resultado indeterminado puede interpretarse mejor como falso, según la opción más segura.

Sin embargo, esto aún permitiría informar el resultado como indeterminado, por lo que este matiz adicional del valor no se perdería por completo, hasta el punto en que el valor se pueda resolver y restablecer definitivamente.

Lee Leon
fuente