在我看来,您应该返回在上下文中语义正确的值,无论它是什么。一条“总是返回一个空集合”的规则对我来说似乎有点简单。
假设在一个医院系统中,我们有一个函数应该返回过去 5 年所有以前住院的列表。如果客户没有住院,返回一个空列表是很有意义的。但是,如果客户将准入表格的那部分留空怎么办?我们需要一个不同的值来区分“空列表”与“没有答案”或“不知道”。我们可以抛出异常,但这不一定是错误条件,也不一定会让我们脱离正常的程序流程。
我经常对无法区分零和无答案的系统感到沮丧。我有很多次系统要求我输入一些数字,我输入零,然后我收到一条错误消息,告诉我必须在此字段中输入一个值。我刚刚做了:我输入了零!但它不会接受零,因为它无法区分它和没有答案。
回复桑德斯:
是的,我假设“此人未回答问题”和“答案为零”之间存在差异。这就是我回答的最后一段的重点。许多程序无法将“不知道”与空白或零区分开来,这在我看来是一个潜在的严重缺陷。例如,大约一年前我正在买房子。我去了一个房地产网站,上面列出了许多要价为 0 美元的房子。对我来说听起来不错:他们免费赠送这些房子!但我确信可悲的现实是他们只是没有输入价格。在这种情况下,你可能会说,“嗯,显然为零意味着他们没有输入价格——没有人会免费赠送房子。”但该网站还列出了各个城镇房屋的平均要价和售价。我不禁想知道平均值是否不包括零,从而在某些地方给出了错误的低平均值。即 100,000 美元的平均值是多少; 120,000 美元;和“不知道”?从技术上讲,答案是“不知道”。我们可能真正想看到的是 110,000 美元。但我们可能会得到 73,333 美元,这是完全错误的。另外,如果我们在用户可以在线订购的网站上遇到这个问题怎么办? (不太可能适用于房地产,但我相信您已经看到许多其他产品都这样做了。)我们真的希望将“尚未指定的价格”解释为“免费”吗?
RE 有两个独立的功能,一个“有吗?”和“如果是,那是什么?”是的,你当然可以这样做,但你为什么要这样做?现在调用程序必须进行两次调用而不是一次。如果程序员没有调用“any”会发生什么?并直奔“这是什么?” ?该程序会返回一个误导性的零吗?抛出异常?返回一个未定义的值?它会创建更多代码、更多工作和更多潜在错误。
我看到的唯一好处是它使您能够遵守任意规则。这条规则有什么好处,值得费心去遵守它吗?如果不是,那何必呢?
回复 Jammycakes:
考虑实际代码的样子。我知道问题说的是 C#,但如果我写 Java,请原谅。我的C#不是很犀利,原理是一样的。
返回空值:
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
使用单独的功能:
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
它实际上是一个或两行代码,返回 null,所以它不是给调用者更多的负担,而是更少。
我看不出它是如何造成 DRY 问题的。这不像我们必须执行两次调用。如果我们总是想在列表不存在时做同样的事情,也许我们可以将处理下推到 get-list 函数而不是让调用者来做,因此将代码放在调用者中将违反 DRY。但我们几乎可以肯定不想总是做同样的事情。在我们必须处理列表的函数中,缺少列表是一个很可能会停止处理的错误。但是在编辑屏幕上,如果他们还没有输入数据,我们肯定不想停止处理:我们想让他们输入数据。因此,必须以一种或另一种方式在调用者级别处理“无列表”。我们是否使用 null 返回或单独的函数来执行此操作对更大的原则没有影响。
当然,如果调用者不检查空值,程序可能会因空指针异常而失败。但是,如果有一个单独的“获取任何”函数并且调用者没有调用该函数而是盲目地调用“获取列表”函数,那么会发生什么?如果它抛出异常或以其他方式失败,那么这与如果它返回 null 并且没有检查它所发生的情况几乎相同。如果它返回一个空列表,那就错了。您无法区分“我有一个零元素的列表”和“我没有一个列表”。这就像当用户没有输入任何价格时,价格返回零:这是错误的。
我看不出将附加属性附加到集合有什么帮助。调用者仍然需要检查它。这比检查 null 有什么好处?同样,可能发生的最糟糕的事情是程序员忘记检查它,并给出错误的结果。
如果程序员熟悉 null 意思是“没有值”的概念,返回 null 的函数并不奇怪,我认为任何有能力的程序员都应该听说过,无论他是否认为这是一个好主意或不。我认为拥有一个单独的功能更像是一个“惊喜”问题。如果程序员不熟悉 API,当他在没有数据的情况下运行测试时,他会很快发现有时他会返回 null。但是他怎么会发现另一个函数的存在,除非他想到可能存在这样的函数并且他检查了文档,并且文档是完整且易于理解的?我宁愿拥有一个总是给我一个有意义的响应的函数,而不是两个我必须知道并记住调用两者的函数。