当您无法确定布尔值时该怎么办?


38

我们正在为公司构建一个Web应用程序,到目前为止,该管理仅存在于Excel工作表中。到现在我们已经差不多完成了,但是最近我被分配了一个任务,将所有数据从这些工作表导入到我们的新系统中。该系统是用Java构建的,但是由于这种导入只是一次性的事情,因此我决定改用Python编写脚本,然后直接通过SQL查询将其导入。问题来了。新数据模型包含一些新属性,这些新属性未包含在其现有数据中。在大多数情况下,这不是问题,我在找不到信息的地方放了一个null。但是随后我遇到了一些属性,它们是布尔值,默认情况下不能为NULL。首先,我尝试只允许数据库中的这些字段为空,但是我的资深开发人员告诉我不要这样做,因为这将来会在我们的系统中引起问题。现在我不太确定该怎么做。显而易见的解决方案是将每个未知布尔值默认设置为false,但是我认为这也是错误的,因为我实际上不知道它是否为false。

示例:假设您有一个具有hasRadio参数的实体Car。现在,您需要将数据导入此数据模型,但是在数据中只有“模型”和“颜色”列,关于是否具有无线电没有任何内容。如果设计上不能将其设置为空,那么您将在“ hasRadio”列中添加什么?

在这种情况下最好的方法是什么?我们是否应该告诉公司手动填写丢失的数据?还是默认为false?


70
对我来说,允许NULL是正确的解决方案。您的上级是否比“将来在我们的系统中引起问题”更具体?如果不是,请询问他更多具体原因。
larsbe

48
FileNotFound显然,您应该将其默认设置为。

7
是否可以添加一个布尔值字段“ isValidHasRadio”或其他内容,还是会破坏事情?
海德

9
正确的解决方案是考虑输入数据为垃圾,并中止整个事务,然后,如果不能认为该数据是垃圾,则要求调整任务定义。这里没有别的办法。
Sarge Borsch

17
顺便说一句,我不是空值的忠实拥护者。我宁愿使用带有“未知”,“有广播”和“没有广播”的枚举。这样,您就可以满足自己的要求,并且如果将来必须指定一种无线电类型,例如“带有集成电视的无线电”之类的东西,则还有很大的发展空间。
马查多

Answers:


129

这主要是一个需求分析问题,与所涉及的数据为“布尔值”无关。如果必须初始化数据库或任何其他类型的数据存储中的表,并且某些列的输入不完整,则首先需要找出系统用户或客户认为正确的默认值的内容对于这些列,您需要为每个单个属性找出答案,通常没有正确的答案。

这通常会导致以下情况之一:

  • 特定列有一个很好的默认值,用户不必介意所有记录的初始值是否相同,以后可以在需要时轻松设置正确的值

  • 有一条规则可以根据其他信息确定理想的默认值,因此您可以将此规则放入代码中

  • 用户或您的客户将在将输入数据导入数据库之前扩展输入数据并提供缺失值(可能是手动提供)

  • 对于特定的列和/或任何记录,没有很好的默认值,也应该导入数据,但是用户想知道特定值已经针对哪些记录进行了初始化,而哪些则没有初始化。因此,他们可以在之后输入值,并跟踪已正确设置值的记录和未正确设置的记录。

最后一种情况需要NULL之类的值来表示未初始化或未知状态,即使对于布尔值也是如此,无论您的上级是否喜欢。如果出于某种技术原因,禁止在特定的列中使用NULL值,则需要以其他方式模拟“未知”状态,方法是引入一个额外的布尔列(如hasRadioIsUnknown),或使用3 -valued枚举,而不是一个布尔(如HasNoRadio=0HasRadio=1Unknown=2)。但是,在您进行了彻底的需求分析之后,请与您的上级再次交谈,以确保确实有必要采取这种解决方法。


29
您还应该注意,相同的答案适用于您方便使用NULL的其他列。您应该验证这是否是正确的默认值。例如,如果其他列显示“ processingIsFinished”,而您从客户的订单历史记录中导入了旧数据(例如网上商店),则可能需要将值设置为“ true”而不是“ NULL”,以避免触发某些流程当他们遇到尚未处理的条目时(根据他们对该列的解释)。
Frank Hopkins

1
这是一个功能问题。由于模型(优秀模型和新模型)不匹配,因此应考虑这些情况来审查迁移过程。唯一可以说如何进行的是利益相关者(客户或任何人)。从技术上讲,您可以通过多种方式解决此问题,但在功能上只能解决一种。正确的。
Laiv

12
我喜欢这种故障。在这种情况下,我对null的不满意主要是因为它缺乏明确的含义。未知是清楚的。但是null表示未知还是不适用?谁会知道?仅仅因为它对您有意义,并不意味着其他所有人也会以相同的方式看到它。
candied_orange

选项4:缺少特定列值的记录实际上是无用的,应从导入中排除。选项5:导入之前,需要校正所有传入的数据。很多选择,仅取决于需求和预算。导入旧数据总是一团糟。
jpmc26

@ jpmc26:好吧,我没有包含选项4,因为我想保留OP实际写的内容(这种情况下,丢失的数据绝对不包括在导入数据中,没有记录)。选项5确实值得一提,因为它是避免使用NULL值的另一种方法。相应地编辑了我的答案。
布朗

39

这不是技术问题;这是一个业务规则问题。因此,您需要询问“业务”。

与产品所有者和/或利益相关者联系,并说出类似以下内容:

对于您在应用程序中请求的字段之一,我们的数据不完整。您希望我们使用默认值吗?您是否希望我们添加“未知”作为有效值?或者,您是否希望团队中的某人在导入之前更正数据?

可能会进行一些讨论。但是,基本上就是这样。技术解决方案将自然地从更加完善的业务规则中产生。


9

一般的问题是称为数据清理的整个编程子区域,这是称为数据集成的较大子区域的一部分。避免此类问题很可能是从Excel工作表迁移的主要原因,也是为什么高级开发人员不希望允许字段变为可为空的原因。我认为这是数据迁移中较大的复杂性来源之一,这并不是没有道理的。

仅在可能的情况下选择使用NULL可能是很错误的事情,更不用说更改数据模型以使更多字段可为空了。Excel的完整性检查较弱或没有,这很可能是其中许多问题的原因。错误的做法是删除新数据库中的完整性检查并将垃圾转储到其中。这只是使问题永久存在,并为将来的集成增加了极大的复杂性,而这些集成必须以某种方式处理无意义的数据。

某些差异可能是由于数据模型不匹配造成的。处理此问题主要是(密切地)熟悉两个数据模型并知道如何将旧模型映射到新模型。只要新能够捕获旧的。(否则,您的团队可能会遇到很大的问题。)这可能很容易需要做更多的工作,而不仅仅是复制列。Darkwing给出了一个很好的例子(以及为什么盲目插入NULL是错误的做法)。在阐述它,如果旧的模式有一个ReceivedDateInProgress位和新的模式有一个StartDateProcessingEndTime,你将需要决定是否以及如何设置ProcessingEndTime。根据使用方式,合理(但任意)的选择可能是将其设置为与StartDate (或者不久之后会导致问题)。

但是,某些差异可能是由于“应该”存在的丢失或损坏的数据造成的。(很可能是由于数据输入错误或过去处理不当或数据处理系统中的错误引起的。)如果您的团队中没有人预料到这一点,那么您(集体)将自己花费在项目的20%上的时间设定为“几乎”完成。(这是一个虚构的数字,但可能很比这更糟,甚至更好。这取决于多少数据不正确,它有多重要,它有多复杂,从负责数据的人员那里介入的难易程度,以及其他因素。)一旦确定数据“应该是”,但不见了。通常,您将尝试通过查询旧数据源来确定问题的严重程度。如果有数十个或数百个条目,则很可能是数据输入错误,负责数据的客户应手动解决它(即告诉您值应该是什么)。如果是数百万个条目(或数据的很大一部分) ,那么您可能需要重新考虑是否正确地识别出“应该”存在。这可能表明新系统中存在建模错误。

例如,假设一张发票有数量和每个项目的总和(但没有单价),只是其中一些数量莫名其妙地丢失了。与处理此类发票的人交谈可能会产生以下一种(或多种)情况:1)“哦,空白数量表示数量为1”,2)“哦,我知道这些物品的价格大约为$ 1,000,所以,显然,这是2的订单,3)“发生这种情况时,我在另一个系统中查找价格并四舍五入”,4)“我在另一个系统中查找价格”,5)“那不是真实数据”,6)“以前从未见过”。

如建议的那样,这可以指示自动解决情况的某些方法,但是您必须注意该解决方案适用于所有情况。涉及其他系统可以交叉检查数据是很常见的,这是一件好事。但是,这通常是一件坏事,因为很难获得访问权限并与这些系统集成以执行交叉检查,并且经常发现,系统之间的冲突不仅仅是因为丢失了一些数据。通常需要一些手动干预,并且取决于规模,很可能需要专门为数据清理任务创建工具和界面。通常,完成的工作是部分导入数据,但是将缺少数据的行发送到单独的表中,以便在其中查看它们。


14
总结:如果您认为处理遗留代码不愉快,请尝试处理遗留数据。
彼得·泰勒

0

更改数据模型。

您可以规范化hasradio,那么您将不再有任何null。

如果无法确定布尔值,请不要使用布尔值。

通过允许布尔值变为null,它将不再是布尔值。布尔值可以具有2个状态:False,True。

您需要的是3个状态:错误,正确,未知。

您可以选择更改数据模型吗?

(还有我想到的另一件事,如果在python或java中从数据库中检索数据。检索记录,检查hasradio字段,如果检查它是true还是false并且它碰巧为null,会发生什么?)


2
通过改变数据模型和“正常化出hasRadio”,我想你的意思是像添加新表CarFeatures,包含字段Car_IDFeature_IDHas_Feature?似乎是个好主意。
jpa

2
@jpa有点棘手的情况。您必须非常清楚自己的工作,因为在我们的情况下没有记录意味着未知。尽管通常没有记录意味着它没有该功能。
Pieter B

1
彼得,你看错了。没有人说过a bool具有两个以上的值,因为正如您所说,它没有。A booltruefalse。但是,在OP的情况下,OP并不bool直接处理,而是Option<bool>/Maybe<bool>可以处理Some -> true/false或的None
安迪

@DavidPacker我的观点是,由于它是Maybe <bool>,您应该停止对其进行任何远程相似的调用,否则您会感到困惑。而且,如果您坚持使用布尔值,则可以找到一种安全的方法。
Pieter B

4
在我看来,可以为null的布尔值完全可以。我从未遇到过null值的问题,尽管我遇到过这样做的开发人员。
安迪

-1

正如其他人所指出的,这里的值是一个布尔值,它不是真正的布尔值,问题是要么强制其为布尔值,要么以其他方式处理它。

您可以做的是,没有两个布尔结果,而只有一个布尔结果。这些可以同意也可以不同意。如果他们同意,那么您将获得直接的正确/错误结果。

但是,如果他们不同意,那么您将获得不确定的结果,并且您有机会根据出现这种情况的情况来决定如何处理该结果。在某些情况下,根据最安全的选择,最好将不确定结果最好解释为true,而在其他情况下,最好将同一不确定结果最好解释为false。

不过,这仍然允许将结果报告为不确定的,因此,直到可以确定解析并重置该值之前,该值的其他细微差别也不会完全丢失。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.