我听到一些声音说,检查从方法返回null值是糟糕的设计。 我想听到的一些原因。
伪代码:
variable x = object.method()
if (x is null) do something
我听到一些声音说,检查从方法返回null值是糟糕的设计。 我想听到的一些原因。
伪代码:
variable x = object.method()
if (x is null) do something
背后不返回空的理由是,你没有检查它,因此你的代码并不需要遵循根据返回值不同的路径 。 您可能要检查出空对象模式 ,提供更多相关信息。
例如,如果我定义Java中的方法,该方法返回一个Collection我通常喜欢返回一个空的集合(即Collections.emptyList()
而不是零,因为这意味着我的客户端代码更干净; 例如
Collection<? extends Item> c = getItems(); // Will never return null.
for (Item item : c) { // Will not enter the loop if c is empty.
// Process item.
}
......这比清洁:
Collection<? extends Item> c = getItems(); // Could potentially return null.
// Two possible code paths now so harder to test.
if (c != null) {
for (Item item : c) {
// Process item.
}
}
这里的原因。
在清洁守则由罗伯特·马丁 ,他写道,返回null是不好的设计时,你可以改为返回,也就是说,空数组。 由于预期的结果是一个数组,为什么不呢? 这将让您遍历结果没有任何额外条件。 如果它是一个整数,也许0就足够了,如果它是一个哈希空哈希。 等等
前提是不强制调用代码立即处理的问题。 调用的代码可能不希望与他们关注自身。 这也是为什么在很多情况下的例外是比无好。
返回null的好用途:
坏用途:试图更换或隐藏特殊情况下,如:
在这种情况下抛出异常是比较充足的,因为:
然而,异常不应该被用来处理程序的正常运行条件,例如:
是的,返回NULL是一个可怕的设计 ,面向对象的世界。 简而言之,NULL用法导致:
检查的详细说明这个博客帖子: http://www.yegor256.com/2014/05/13/why-null-is-bad.html 。 更多在我的书优雅的对象 ,第4.1节。
谁说,这是不好的设计?
检查空值是家常便饭,甚至鼓励,否则您将NullReferenceException异常的风险无处不在。 它能够更好地摆好比当你不需要抛出异常处理错误。
根据你已经表示,到目前为止,我认为有没有足够的信息。
从CreateWidget()方法返回null,似乎不好。
从FindFooInBar()方法返回null,似乎罚款。
它的发明者说,这是一个数十亿美元的错误!
这取决于你使用的语言。 如果你喜欢C#语言,其中表示没有值的惯用方式是返回null的时候,然后返回null是一个好的设计,如果你没有价值。 或者,在语言,例如哈斯克尔其惯用使用单子也许对于这种情况,则返回null将是一个糟糕的设计(如果它甚至有可能)。
如果你看过所有的答案就变得明确了这个问题的答案取决于该种方法。
首先,当一些特殊情况发生(IOproblem等),在逻辑上抛出异常。 当究竟什么是例外可能是东西不同的主题..
每当一个方法,预计可能没有结果主要有两类:
我们直到有指示某个功能或不能返回null正式的方式,我努力的命名惯例来表示如此。
就像你有尝试一些()约定为预期失败,我通常命名我的方法安全的东西()时,该方法返回一个中立的结果,而不是空的方法。
我不是这个名字完全确定还没有,但不能拿出更好的东西。 所以我与运行了。
例外情况是情况人。
如果你的函数是为了找到一个给定对象关联的属性,而该对象并没有这样的属性,它可适当返回null。 如果对象不存在,抛出一个异常,可能更合适。 如果该功能是为了返回属性的列表,并且没有人会返回,返回一个空列表是有道理的 - 你返回所有属性数为零。
它的优良返回null,如果这样做在某种程度上是有意义的:
public String getEmployeeName(int id){ ..}
在这样的情况下,它是有意义的返回null,如果id不符合现有的实体,因为它允许你区分在没有匹配的来自合法发现错误的情况。
人们可能会认为这是不好的,因为它可以因为用户必须检查返回被滥用作为一个“特殊”的返回值,指示错误条件,这是不太好,有点像从函数返回错误代码,但令人困惑空,而不是捕捉适当的例外,如
public Integer getId(...){
try{ ... ; return id; }
catch(Exception e){ return null;}
}
这不一定是一个糟糕的设计 - 因为有这么多的设计决策,它依赖。
如果该方法的结果是什么,不会有好结果在正常使用时,返回null是罚款:
object x = GetObjectFromCache(); // return null if it's not in the cache
如果真的应该永远是一个非空的结果,那么它可能是更好地抛出一个异常:
try {
Controller c = GetController(); // the controller object is central to
// the application. If we don't get one,
// we're fubar
// it's likely that it's OK to not have the try/catch since you won't
// be able to really handle the problem here
}
catch /* ... */ {
}
我在这方面是我受益匪浅公约
对于单个项目的查询:
Create...
返回一个新的实例, 或抛出 Get...
返回预期的现有实例, 或抛出 GetOrCreate...
如果不存在返回现有实例,或新的实例, 或抛出 Find...
返回现有的实例,如果存在的话, 或null
对于收集查询:
Get...
总是返回一个集合,如果没有匹配的[1]被发现的项目里面是空的[1]中给出的一些标准,显式或隐式的,在功能名称或作为参数给出。
对于某些情况下,你想尽快正好看到一个失败。
检查是否为NULL,而不是断言(用于编程错误),或在故障情况下抛出(用户或来电者的错误)可能意味着以后的崩溃是很难追查,因为原来的奇案件没有被发现。
此外,忽略错误可能会导致安全漏洞。 也许是空的烦躁来自这样一个事实:缓冲区被覆盖等。 现在,你是不是崩溃,这意味着剥削者有机会在你的代码来执行。
你看到返回null什么选择?
我看到两种情况:
在这种情况下,我们可以:返回null或抛出(检查)异常(或者创建一个项目并将其返回)
在这种情况下,我们可以返回null,则返回一个空列表或抛出异常。
我相信,返回NULL可能不如替代好becasue它需要客户记得检查空,程序员忘记和代码
x = find();
x.getField(); // bang null pointer exception
在Java中,抛出检查异常,RecordNotFoundException,允许编译器提醒客户办理情况。
我发现,搜索返回空列表可以很方便 - 只要填充显示与列表中的所有内容,哦,它是空的,代码“只是工作”。
有时,返回NULL是做正确的事,但特别是当你与不同类型(数组,列表,字符串,什么具备的,你)的序列处理它可能是更好返回一个零长度序列,因为它导致短,希望更多的可以理解的代码,而不是承担API实施者的部分更写。
让他们调用另一个方法在事后找出如果以前的电话是空。 ;-)嘿,这是为JDBC不够好
这个线程背后的基本理念是防守编程。 也就是说,对意外的代码。 有不同的答复的数组:
亚当斯基建议看空对象模式,与回复往上投票支持这一建议。
迈克尔Valenty还建议命名约定来告诉开发者有什么可以预期。 ZeroConcept建议正确使用异常的,如果是空的原因。 和别的。
如果我们做了“规则”,我们总是想要做防御性编程,然后我们可以看到,这些建议是有效的。
但是,我们有2种开发方案。
类“创作”由开发商:作者简介
类“消费”的另一个(也许)开发商:开发者
无论一个类是否返回NULL的一个返回值的方法,开发人员将需要测试对象是否有效。
如果开发商不能做到这一点,那类/方法不确定性。 也就是说,如果“方法调用”来获取对象没有做什么“通告”(例如getEmployee的),它打破了合同。
作为一类的作者,我总是想创建一个方法时是作为一种和防御(和确定性)。
因此,考虑到无论是空或空对象(例如,如果(员工为NullEmployee.ISVALID))需要进行检查,并且可能需要与员工的集合发生,那么空对象的方法是更好的方法。
但我也喜欢命名必须返回null如getEmployeeOrNull方法的迈克尔Valenty的建议。
谁抛出一个异常的作者是为开发者测试对象的有效性,这是对象的集合,非常糟糕的去除选择,他们的分支耗费代码时迫使开发者为异常处理。
作为一个开发者消费类,希望笔者给我,以避免他们的类/方法可能会面临零局势的能力或程序。
所以,作为一名开发人员,我将针对来自法NULL防守编程。 如果作者给了我一份合同,它总是返回一个对象(null对象总是这样),而且对象有通过测试对象的有效性的方法/属性,那么我会用这种方法/属性继续使用对象,否则该对象是无效的,我不能使用它。
底线是,类/方法的作者必须提供开发人员可以在他们的防守编程中使用的机制。 也就是说,该方法更清晰的意图。
开发者应该始终使用防御性编程,以测试从另一个类/方法返回的对象的有效性。
问候
GregJF
其他选项这一点,分别是:返回一些值,指示(错误或类型)的成功与否,但如果你只需要布尔值,指示成功/失败,失败返回null,并取得成功的对象不会不太正确的,那么返回true / false,并且通过参数获取的对象。
其他做法都会给使用异常来表示失败,但在这里 - 其实有更多的声音,是说这是一个不好的做法(如使用异常可能是方便,但有许多缺点)。
所以我个人没有看到任何在返回null作为指示出错了,后来检查它(实际上知道,如果你已经成功与否)不好。 此外,盲目地以为你的方法将不会返回NULL,然后你的基础上它的代码,可能会导致其他,有时很难找到,错误(虽然在大多数情况下,它只会造成系统崩溃:),你会参考00000000迟早)。
意外空函数可以在复杂的程序的开发过程中产生的,而像死码,这类事件表明程序结构的严重缺陷。
空函数或方法通常被用作在对象框架revectorable功能或覆写投放方法的默认行为。
Null_function @wikipedia
嗯,这肯定要看的方法的目的...有时候,一个更好的选择将是抛出异常。 这一切都从案例取决于到的情况。
如果代码是一样的东西:
command = get_something_to_do()
if command: # if not Null
command.execute()
如果你有一个虚拟的对象,其execute()方法什么也不做,你返回,而不是空在适当的情况下,你不必检查该空的情况下,可以代替只是做:
get_something_to_do().execute()
所以,这里的问题是不检查NULL与异常之间,但而不必以不同方式处理特殊的非案件(以任何方式),或者不是调用之间。
对于我的使用情况下,我需要回到从方法的地图,然后寻找一个特定的密钥。 但是,如果我返回一个空的地图,然后它会导致空指针异常,然后它不会有太大的不同返回,而不是一个空的地图空。 但是从Java8以后,我们可以使用可选 。 以上是这个原因被引入可选的概念。
天儿真好,
返回NULL,当你无法创建新的对象是许多API的标准做法。
究竟为什么它是不好的设计,我不知道。
编辑:这是在哪里你没有例外,如C,其中它已连续多年惯例语言如此。
HTH
“Avahappy,