Java的Void方法是反模式的? - DZone


如果你想知道为什么你应该避免 void 方法,这篇文章就是为你准备的。在这里,您可以找到他们的所有问题,并了解它们如何影响您的系统。
关于在我们的代码中使用 void 方法,以及我们是否应该将它们视为代码异味。我将介绍 void 关键字的一些基础知识,并提及我们可能认为使用带有此关键字的方法有益的情况。然后我将提供论据向您表明,最终这可能不是一个好主意。 
但首先请记住,本文是从 Java 语言的角度编写的,有些情况可能不适用于您喜欢的语言。
与任何其他关键字一样, void有存在的理由——或者至少看起来如此。在 Java 中,与在 C 派生的其他语言中一样,它用于描述正常执行但不向其调用者提供返回值的方法。 
值得一提的是,在 Java 中,除了void关键字之外,还有Void类型,用于 将void 返回类型表示 为一个类。它只有一个私有构造函数,所以我们不能实例化它。此外,我们可以分配给Void变量的唯一值是null。
在大多数情况下,当我们需要执行具有某种副作用的操作时,我们会使用 void 方法。void 方法最常见的用例是 System.out.println,它将所需的文本打印到标准输出。 
其他例子是:

  • 运行作业或任务,例如使用 main 方法运行 Java 应用程序
  • 执行数据库查询
  • 使用Bean生命周期注解,像@PostCon小号truct
  • 默认情况下,对象属性的设置器是空的

此外,您必须集成的某些库或 API 使用 void 方法,并且通过扩展,您也需要使用它们。javax.mail库可能是一个很好的例子。它最重要的方法SendMessage是 void,因此即使您不想自己使用 void,您仍然可能被迫这样做。
关于我们为什么使用 void 方法 - 通常,这取决于。例如,在打印的情况下,可能很难想出究竟应该返回什么。这同样适用于运行作业或任务,但问题更复杂。对于生命周期注解,没有什么可以返回的。它们只是简单的钩子,仅此而已,即使我们决定从这样的方法返回一些东西,它无论如何都会被省略。
正如你所看到的 void 方法似乎非常有用,所以现在你可能会问:如果它们如此有用,我为什么认为我们应该避免它们?– 和往常一样,我在这里帮助您并提供答案。
 
为什么使用 Void 方法是个坏主意?
  1. 打破封装,可能会导致我们应用程序的一些不必要的实现细节泄漏。此外,它可能导致任何有兴趣参与或解决应用程序相关任务的人都需要更深入的系统知识。对于相对简单的代码库来说,这可能不是一个例子,但它肯定会在更大的应用程序中展现出它的全部“荣耀”。即便如此,我相信我们几乎每个人都忘记调用像public void doSth(..arguments)这样的方法,并花了一个小时左右的时间思考,“为什么我的代码不起作用?”。
  2. 不提供任何合约,就我们有输入和输出而言,我们只有输入,输入后我们有魔法。我们必须猜测方法内部到底发生了什么。在我看来,这是 void 方法的最大问题。您可能会注意到,这是下面描述的所有其他问题背后的原因,至少在某些方面是这样。
  3. 可以限制局部推理,因为您会丢失有关方法实际返回内容的信息。您必须深入了解实现才能了解方法执行的预期结果。当然,描述性命名可能会减少这个问题的影响,但仍然,正常的方法提供了更多的信息,更重要的是这些信息对读者来说更明显。
  4. 明显更难测试。缺乏返回值使得不可能执行任何基于断言的测试。为了验证我们的方法是否按预期工作,我们必须检查它修改的对象的状态(简单情况)或一些扮演生产对应角色的测试数据库的状态(复杂情况)。
  5. 仅因副作用而生存(另一种半反模式,尤其是在函数式编程中)。如果你想在你的代码库中避免或限制它们,你也应该远离void关键字。
  6. 倾向于在代码库中非常快速地传播,因为它看起来是实现我们需要的更容易和更快的方法。

 
所有的 void 方法都是坏的吗?
当然不是,但大多数是。打印到控制台、记录到文件或发送邮件等任务是可以使用 void 方法而不会引起太多问题的很好的例子。然而,在几乎任何其他情况下,至少在我看来,它们应该以尽可能有限的方式避免和使用。 
如果无法限制空隙的使用,则应重点限制它们对整体应用的影响。例如,您可以将它们放在尽可能低的执行顺序中。因此,这种方法的任何失败都可以更好地隔离,并且对我们代码库的风格和内部工作的整体影响将减少。
 
概括
为了清楚起见,我会再说一遍:在大多数情况下,void 方法是不好的,应该被视为反模式,使用它们可能会导致非常有品味的意大利面条式代码,其中所有内容都隐式有状态。