Oop 允许超过一个;“没有价值”;价值空间中的价值

Oop 允许超过一个;“没有价值”;价值空间中的价值,oop,design-patterns,design-principles,Oop,Design Patterns,Design Principles,我在所有域对象上使用字符串类型作为Id属性。例如: public class Person { property string Id { get; set; } // ... more properties } 这里没有诡计null表示一个“无值”值,当创建一个新的人员并且在其被持久化之前,Id将保持null 现在有一个关于增强“无值”空间的讨论,它说null、空字符串和空白字符串都是“无值”值 也就是说,检查实体是否是新的,而不是执行以下操作:if(person.Id==nu

我在所有域对象上使用字符串类型作为Id属性。例如:

public class Person {
    property string Id { get; set; }
    // ... more properties
}
这里没有诡计
null
表示一个“无值”值,当创建一个新的人员并且在其被持久化之前,
Id
将保持
null

现在有一个关于增强“无值”空间的讨论,它说
null
、空字符串和空白字符串都是“无值”值

也就是说,检查实体是否是新的,而不是执行以下操作:
if(person.Id==null)
它将变成
if(string.IsNullOrWhiteSpace(person.Id))

依我的拙见,这是一种气味或违反了设计原则,但我不知道是哪一种

问题:此决定违反了哪项(如果有的话)设计原则(允许不只是
null
表示无值的决定)


(我认为它应该类似于Occam的剃刀原理或熵或KISS,我只是不确定)

我要冒险说定义
null
”,因为应用程序的空字符串不违反任何设计原则,也不是代码味道。您只需为自己的目的明确定义字段的语义,您已经这样做了(即,在应用程序中,但是
null
表示“无值”)

您应该进行测试,以确保
null
的行为都是正确的

这并不是说您也不能决定强制所有空字符串为null。这是一个同样有效的决定。您需要进行测试,以验证在设置“无值”的所有情况下,实际值是否为空。如果持久性层期望null,并且只有null表示没有值,那么您可能希望这样做


所以,在这种情况下,没有错误的决定,只有决定

这确实违反了接吻原则。如果不需要特别处理空字符串旁边的空字符串,那么为什么要这样做呢?所有操作现在必须检查两个值,而不是一个值。在探索数据库时,一个查找“NULL”记录的简单选择变得不那么琐碎,没有什么好的理由

另一个被违反的原则是最小惊奇原则——通常人们只希望空值代表空对象。带有两个特殊值的设计不太明显,也不太“可读”

如果在这些“第二类特殊对象”背后还隐藏着更多的东西,那么它应该被明确化。否则,处理空字符串输入并将其存储为NULL以与系统的其余部分保持一致应该很简单

编辑:


我还在鲍勃·马丁的书中发现了另一个“原则”——“每个概念一个词”,这与本案有某种关联。空字符串和空值是用于一个概念的两个“单词”,因此它们显然违反了此准则。

为什么建议的更改在您看来是糟糕的设计?除了“无值”将由多个
Id
值表示这一事实之外,还有什么其他原因吗?应用程序当前如何处理空Id值或空白Id值?我的草稿参数是-系统越简单越好。假设较少的系统更简单。构建在“无值”=null上的系统有一个更少的假设,而构建在“无值”上的系统是一个null或空字符串的系统。就个人而言,我不喜欢在Id中具有相同含义的不同值的想法。空字符串甚至“空白字符串”从何而来?我将实现setter来执行值的清理,或者更好:拒绝设置没有意义的值(例如空字符串)。取决于上下文。再说一遍:这些字符串是从哪里来的?你数据库里的什么地方?从某个文件中?如果它是一些手工编辑的文件,那么您读取该文件的代码可能会对其进行清理。如果这些值来自数据库:为什么它们会存在?@mdo:即使空格
Id
确实来自外部,我也可以在setter中强制它为null,正如您所说。好吧,这是一个简单的演示,说明为什么它可能不好:如果可以用一个空的sting和无限多的空格字符串扩展无值范围。可以添加任何其他任意值,例如“NO-VALUE”、“NV”、“噢!NO!”和“this not VALUE”。从实用的角度来看,不,使用该假设的每个测试都应该对每个无值进行测试。您的逻辑是完全不符合逻辑的。如果只有空白定义没有值,那么非空白定义没有值,那么字符串是一组“无限”值。如果在“无值”集合的定义中不存在包含空字符串和所有空白值的问题,则同样可以使用该字符串集合的其他预定义值进一步扩展该“无值”集合。例如,如果Id是{null,“,”,“no-value”}中的一个,那么它就没有值。我并不是说任何非空白都没有价值。我建议使用几个固定值。显然,您只需要null。在分析后做出明智的决定和代码气味/糟糕的设计原则之间仍然有区别。@THX-1138-你正在滑向一个滑坡谬论。空白字符串和“NO-VALUE”之间存在重要的语义和常规差异,因此“NO-VALUE”不像“NO-VALUE”集合中的“”那样合适。框架中没有
string.IsNOVALUE
测试方法,但有一个用于空格的方法-这是它们之间存在重要差异的线索。我同意你的观点。我想知道奥卡姆的剃须刀是否可以在这里使用。本质上,我们有两个替代系统-在一个系统中正好有一个无价值值,在另一个系统中有两个等价的无价值值。显然,第一个系统更简单(因此KISS是令人满意的)。尽管奥卡姆的剃须刀有点反方向工作(从观察到理论)。