空检查的频率和地点

时间:2019-01-03 08:13:07

标签: java api clean-architecture

我正在尝试避免过度执行null检查,但与此同时,我想在需要使代码健壮的任何时候进行null检查。但是有时候我觉得它开始变得防御性很强,因为我没有实现API。然后,我避免了一些空检查,但是当我开始单元测试时,它开始总是等待运行时异常。什么是正确的方法,如何感觉平衡。这是我到目前为止收集的笔记:

  • 避免在实例类的私有方法中进行不必要的空检查,因为在进行适当的空检查之前,实例类对此负责,而不是对每个函数负责
  • 在公共方法中进行空检查,并在合同中解释函数行为以供公共使用
  • 在构造函数中进行空检查

让我举一个虚拟的例子,让我开始困惑:

这是界面的默认功能:

default void someFunction() {

// instantiaded foo and filters
foo = processFoo(foo, filters);

// do some operations with foo
// null check if processFoo's contract returns null (description in the implementation)

}

实施:

Foo processFoo(foo, filters) {
// Should I null check foo and filters?

// Operations with foo.someFields
// Operations with filters.someFields

return foo; // If I null check then I should return some exception or null to the caller function. 
// If I don't null check just return received foo.
}

3 个答案:

答案 0 :(得分:4)

一般来说,在控制调用的过程中,我从不检查null,但是如果我的代码可以被其他人调用,则我会强制执行检查,因为您在谈论API规范,所以您可能会检查输入参数并抛出IllegalArgumentException。

当然,在大多数情况下,这不是必需的,当您拥有NPE时,某个地方存在潜在的错误,但是,如果您不能完全控制呼叫,则肯定需要付出额外的努力。 (特别是如果您的API将被频繁调用,则需要一些帮助您跟踪/识别错误调用模式的东西)。

在设计API时,除了架构本身之外,您还必须专注于维护/故障排除和安全性,尤其是如果API是公开的(这意味着还要清理每个参数)。

答案 1 :(得分:1)

如果您已在项目中实现分层,则执行空检查的好地方是从外部接收数据的层。例如:控制器,因为它从用户那里接收数据...或网关,因为它从存储库接收数据。

但是,如果您有能力控制方法的返回值以不返回null,那将是很好的。这将使您能够编写更少的空检查代码,因为您可以通过这种缺失值来“鸵鸟”。 Java为我们提供了这样的类/方法,例如Optional,Java 11的Reader.nullReader()Writer.nullWriter()Collections.empty{List|Map|Set|...}()中的空集合。

当然,您可以创建自己的null对象,以便它可以以不影响程序使用的方式变形。

答案 2 :(得分:1)

在这里扮演恶魔的拥护者,是因为似乎有些人发表评论似乎不喜欢“ null”的概念或在程序中使用它。

“ null”并不是丝毫可以避免的东西,如果您尝试这样做,将会遇到失败。创建对象并为此类对象在内存中分配空间是不必要的,因为如果您的代码在收到“ null”值时会中断,那么在处理它根本无法处理的对象时,它肯定也会中断。不仅如此,而且使用许多Java方法也会遇到失败。

如果可以避免使用'null'并为代码提供更好的处理方式,请这样做。否则,请勿折断背部和脊椎,以免受伤。


最后,回答您的问题:

不确定 是否可以返回“空”值时,您可以输入空检查。例如,如果调用未创建的方法,并且该方法被设计为返回对象,并且该方法可能返回空值,则为此情况添加特殊检查。如果您知道永远不会收到null值(例如,您自己设计了一个方法永远不会返回'null'),则无需进行任何null检查。

此外,如果您仅使用内部或私有方法,并且您知道没有像在示例中那样传递空参数,那么也不必添加空检查。这也适用于您提到的构造函数实例。否则,作为公共方法的经验法则,最好使用空检查,即使仅抛出IllegalArgumentException或返回失败也是如此。