Что делать, если вы не можете определить логическое значение?

38

Мы создаем веб-приложение для компании, администрация которой до сих пор существовала только в таблицах Excel. Мы почти закончили, но недавно мне было поручено импортировать все их данные из этих листов в нашу новую систему. Система построена на Java, но так как этот импорт является единовременным, я решил вместо этого написать сценарии на Python и импортировать их напрямую с SQL-запросами. Здесь возникает проблема. Новые модели данных содержат некоторые новые атрибуты, которые не включены в их существующие данные. В большинстве случаев это не проблема, я просто ставлю ноль, где я не могу найти информацию. Но затем я наткнулся на несколько атрибутов, которые являются логическими и по умолчанию не могут иметь значение NULL. Сначала я попытался разрешить пустое значение для этих полей в нашей базе данных, но мой старший разработчик сказал мне не делать этого, как это может вызвать проблемы в нашей системе в будущем. И теперь я не совсем уверен, что делать. Очевидное решение состоит в том, чтобы присвоить каждому неизвестному логическому значению значение false, но я думаю, что это тоже неправильно, потому что я на самом деле не знаю, является ли оно ложным.

Пример: допустим, у вас есть объект Car, у которого есть параметр hasRadio. Теперь вам нужно импортировать данные в эту модель данных, но в данных есть только столбцы «Модель» и «Цвет», но в них нет или нет радио. Что вы помещаете в столбец hasRadio, если он не может быть нулевым по дизайну?

Каков наилучший подход в этой ситуации? Должны ли мы просто сказать компании, чтобы вручную заполнить недостающие данные? Или по умолчанию это false?

Liberul
источник
70
Для меня разрешение NULL было бы правильным решением. Был ли ваш старший более конкретным, чем «вызывать проблемы в нашей системе в будущем»? Если нет, спросите его по более конкретным причинам.
Ларсбе
48
Вы должны по умолчанию это FileNotFound, очевидно.
Вам
7
Можно ли добавить логическое поле «isValidHasRadio» или что-то в этом роде, или это тоже сломает вещи?
Хайд
9
Правильное решение состоит в том, чтобы считать входные данные мусором и прервать всю транзакцию, а затем потребовать корректировки определения задачи, если эти данные не следует считать мусором. Здесь нет другого пути.
Sarge Borsch
17
Кстати, я не большой поклонник нулевых значений. Я бы предпочел использовать перечисления с «Неизвестно», «Есть радио» и «Не имеет радио». Таким образом, вы будете удовлетворены вашими требованиями и сможете расти, если в будущем вам нужно будет указать тип радио, например, «Радио со встроенным телевизором» или что-то в этом роде.
Мачадо

Ответы:

129

Это, в основном, проблема анализа требований, и она не имеет ничего общего с тем фактом, что данные, о которых идет речь, являются «логическими». Если вам нужно инициализировать таблицы в базе данных или в любом другом типе хранилища данных, и у вас есть неполный ввод для некоторых столбцов, вам сначала нужно выяснить, что пользователи системы или ваш клиент считают правильным значением по умолчанию для этих столбцов, и вам нужно выяснить это для каждого отдельного атрибута , обычно нет правильного ответа.

Это обычно приводит к одному из следующих случаев:

  • для определенного столбца есть хорошее значение по умолчанию, пользователи не возражают, если значение изначально одинаково для всех записей, они могут легко установить правильные значения впоследствии при необходимости

  • есть правило, как определять идеальное значение по умолчанию из другой информации, поэтому вы можете поместить это правило в код

  • пользователи или ваш клиент расширят входные данные и предоставят пропущенные значения (возможно, вручную), прежде чем они будут импортированы в базу данных.

  • для определенного столбца и / или любой записи нет подходящего значения по умолчанию, данные также следует импортировать, но пользователи хотят знать, для какой из записей конкретное значение уже инициализировано, а для какого - нет. Таким образом, они могут впоследствии ввести значение и отследить, для каких записей это значение уже правильно установлено, а для каких нет.

В последнем случае требуется что-то вроде NULL для представления неинициализированного или неизвестного состояния, даже для логического значения, нравится это вашему старшему или нет. Если есть какая-то неясная техническая причина, которая запрещает использование значения NULL для определенного столбца, вам необходимо смоделировать «неизвестное» состояние другим способом, либо введя дополнительный логический столбец (например hasRadioIsUnknown), либо используя 3 значное перечисление вместо булева (например HasNoRadio=0, HasRadio=1, Unknown=2). Но поговорите со своим старшим снова, после того, как вы сделали тщательный анализ требований, чтобы убедиться, что такой обходной путь действительно необходим.

Док Браун
источник
29
Вы также должны заметить, что тот же ответ относится и к другим столбцам, где вы удобно использовали NULL. Вы должны убедиться, что это правильное значение по умолчанию. Например, если в каком-то другом столбце написано «processingIsFinished» и вы импортируете старые данные из истории заказов клиентов (например, в интернет-магазине), вам может потребоваться установить значение «true», а не «NULL», чтобы избежать запуска некоторых процессов. когда они сталкиваются с записями, еще не обработанными (согласно их интерпретации этого столбца).
Фрэнк Хопкинс
1
Это функциональная проблема. Поскольку модели (как отличные, так и новые) не совпадают, процесс миграции должен быть пересмотрен с учетом этих случаев. Единственное, что может сказать, как действовать - это заинтересованные стороны (клиент или кто-либо еще). Технически вы можете решить эту проблему многими способами, но функционально только одним. Право.
Laiv
12
Мне нравится это расстройство. Мое отвращение к нулю в этом контексте в основном связано с отсутствием ясного смысла. Неизвестное ясно. Но означает ли null неизвестность или неприменимость? Как кто-нибудь узнает? То, что это имеет для вас смысл, не означает, что все остальные увидят это так же.
candied_orange
Вариант 4. Записи, в которых отсутствует определенное значение столбца, фактически бесполезны и должны быть исключены из импорта. Вариант 5. Кто-то должен исправить все входящие данные, прежде чем они будут импортированы. Много вариантов, зависит только от потребностей и бюджетов. Импорт старых данных всегда огромный беспорядок.
jpmc26
@ jpmc26: ну, я не включил вариант 4, так как я хотел придерживаться того, что буквально написал OP (случай, когда отсутствующие данные определенно не включены в данные импорта, из-за отсутствия записи). Вариант 5 действительно стоит упомянуть, поскольку это еще один способ избежать необходимости в значениях NULL. Отредактировал мой ответ соответственно.
Док Браун
39

Это не технический вопрос; это вопрос бизнес-правил. Итак, вам нужно спросить «бизнес».

Обратитесь к владельцу продукта и / или заинтересованным сторонам и скажите что-то вроде:

У нас есть неполные данные для одного из полей, которые вы запросили в приложении. Вы хотите, чтобы мы использовали значение по умолчанию? Вы хотите, чтобы мы добавили «unknown» в качестве допустимого значения? Или вы хотите, чтобы кто-то из вашей команды исправил данные перед импортом?

Некоторое обсуждение, вероятно, последует. Но это в основном все. Техническое решение естественным образом вытекает из более четких бизнес-правил.

svidgen
источник
9

Общая проблема - это целая область программирования, называемая очисткой данных, которая является частью более широкой области, называемой интеграцией данных. . Избежание подобных проблем, вероятно, является основной причиной перехода с листов Excel и того, почему старший разработчик не хочет, чтобы поле стало обнуляемым. Я не думаю, что неразумно говорить, что это один из самых больших источников сложности при переносе данных.

Просто предпочитаю использовать NULL , когда вы могли бы, вероятно , очень уж неправильно , не говоря уже об изменении модели данных, чтобы сделать еще больше полей обнуляемыми. В Excel слабая проверка или проверка целостности отсутствует, что, вероятно, является причиной многих из этих проблем. Неправильное действие - удалить проверку целостности в новой базе данных и выбросить в нее мусор. Это только увековечивает проблему и значительно усложняет будущие интеграции, которые должны как-то иметь дело с бессмысленными данными.

Некоторая разница, вероятно, связана с несоответствием модели данных. Работа с этим во многом зависит от того, насколько хорошо вы знакомы с обеими моделями данных и как сопоставить старую и новую. До тех пор , как новый один является способным захватывать старый. (Если нет, ваша команда, вероятно, столкнулась с очень большой проблемой.) Для этого может потребоваться больше работы, чем просто копирование столбцов. Darkwing дает превосходный пример этого (а также, почему слепая вставка NULLs является неправильной вещью). Разбираясь с этим, если у старой модели было «а» ReceivedDateи « InProgressнемного», а у новой модели есть « StartDateи» ProcessingEndTime, вам нужно будет решить, следует ли устанавливать и как ProcessingEndTime. В зависимости от того, как он используется, разумным (но произвольным) выбором может быть его установка таким же, какStartDate (или вскоре после этого, если это вызовет проблемы).

Однако некоторая разница, вероятно, связана с тем, что данные, которые «должны» быть, отсутствуют или повреждены. (Скорее всего, из-за ошибок ввода данных или плохо обработанных прошлых миграций или ошибок в системах обработки данных.) Если никто в вашей команде не ожидал этого, то вы (в совокупности) настроили себя на то, чтобы тратить 20% времени проекта » почти сделано. (Это был выдуманный номер, но это может быть далекохуже этого или лучше. Это зависит от того, какой объем данных неверен, насколько он важен, насколько он сложен, насколько легко привлечь тех, кто отвечает за данные, и других факторов.) Как только вы определили, что данные «должны быть "там, но отсутствует. Обычно вы пытаетесь определить масштаб проблемы, запрашивая старые источники данных. Если это десятки или сотни записей, то, вероятно, это ошибки ввода данных, и клиенты, ответственные за данные, должны вручную разрешить их (то есть сообщить, какими должны быть значения.) Если это миллионы записей (или значительная часть данных) тогда вам может понадобиться пересмотреть, правильно ли вы определили, что это «должно быть» там. Это может указывать на ошибку моделирования в новой системе.

Например, представьте счет-фактуру, в котором были указаны количества и итоги по каждой позиции (но не цена за единицу), за исключением того, что некоторые количества по необъяснимым причинам отсутствовали. Разговор с человеком, который обрабатывает такие счета, может привести к одному (или нескольким) из следующих сценариев: 1) «о, пустое количество означает количество 1», 2) «о, я знаю, что эти товары стоят около 1000 долларов, ясно, что это заказ на 2 ", 3)", когда это происходит, я смотрю цену в этой другой системе и делю и округляю ", 4)" Я смотрю это в другой системе ", 5)" это не реальные данные ", 6)" никогда раньше не видел ".

Как предполагается, это может указывать на некоторые способы автоматического разрешения ситуации, но вы должны быть осторожны, чтобы решение применимо ко всем случаям. Обычно другие системы участвуют в перекрестной проверке данных, и это хорошо. Однако зачастую это плохо, поскольку может быть сложно получить доступ к этим системам и интегрироваться с ними для выполнения перекрестной проверки, и часто обнаруживается, что системы конфликтуют друг с другом, а не только из-за отсутствия некоторых данных. Часто требуется какое-то ручное вмешательство, и в зависимости от масштаба может потребоваться создание инструментов и интерфейсов специально для задачи очистки данных. Часто делается то, что данные частично импортируются, но строки с отсутствующими данными отправляются в отдельную таблицу, где их можно просмотреть.

Дерек Элкинс
источник
14
Итак, если вам кажется, что работать с устаревшим кодом неприятно, попробуйте работать с устаревшими данными.
Питер Тейлор
0

Измените модель данных.

Вы можете нормализовать hasradio, и тогда у вас больше не будет нулей.

Если вы не можете определить логическое значение, не используйте логическое значение.

Если логическое значение становится нулевым, оно перестает быть логическим. Логическое значение может иметь 2 состояния: False, True.

Вам нужно 3 состояния: Ложь, Истина, Неизвестно.

У вас есть возможность изменить модель данных?

(И еще одна вещь, о которой я подумал, если в python или java вы извлекаете данные из своей базы данных. Вы извлекаете запись, проверяете поле hasradio, что произойдет, если вы проверите, является ли оно истинным или ложным, и оно оказывается нулевым?)

Питер Б
источник
2
Изменяя модель данных и «нормализующее из hasRadio», я полагаю , вы имеете в виду что - то вроде добавления новой таблицы CarFeaturesс полями Car_ID, Feature_ID, Has_Feature? Похоже, хорошая идея.
JPA
2
@jpa это немного сложная ситуация. Вы должны быть предельно ясны в том, что делаете, потому что отсутствие записи в нашей ситуации означает неизвестность. Хотя часто отсутствие записи означает, что у нее нет функции.
Питер Б
1
Ты не так смотришь, Питер. Никто не говорит, что a boolимеет более двух значений, потому что, как вы сказали, его нет. А boolэто либо trueили false. Однако, в случае с OP, OP имеет дело не с boolнепосредственным, а скорее с Option<bool>/Maybe<bool>, который может иметь Some -> true/falseили None.
Энди
@DavidPacker мой аргумент состоит в том, что из-за того, что это может быть <bool>, вы должны перестать называть это чем-то удаленно похожим, иначе вы получите путаницу. И если вы настаиваете на использовании логического значения, найдите безопасный способ сделать это.
Питер Б
4
На мой взгляд, nullable boolean вполне нормально. У меня никогда не было проблем с нулевыми значениями, хотя я встречал разработчиков, которые это делали.
Энди
-1

Как уже отмечали другие, здесь у вас есть логическое значение, которое не является действительно логическим, и проблема заключается в том, чтобы либо принудительно заставить его быть логическим, либо обрабатывать его иначе.

Вместо одного логического результата вы могли бы получить два логических результата. Они могут согласиться или не согласиться. Если они согласны, то у вас есть прямой истинный / ложный результат.

Однако, если они не согласны, у вас будет неопределенный результат, и у вас есть шанс, в зависимости от обстоятельств, в которых он возник, принять решение о том, как с этим справиться. В некоторых случаях неопределенный результат может лучше всего интерпретироваться как истина, тогда как в других такой же неопределенный результат может лучше всего интерпретироваться как ложный, в соответствии с наиболее безопасным вариантом.

Это, тем не менее, позволило бы сообщать результат как неопределенный, так что этот дополнительный нюанс значения не будет полностью потерян, вплоть до точки, где значение может быть окончательно разрешено и сброшено.

Ли Леон
источник