【发布时间】:2011-02-15 02:18:43
【问题描述】:
在探索这些问题时,我最近在 Java 中发现了 assert 关键字。起初,我很兴奋。有用的东西我还不知道!一种更有效的方法来检查输入参数的有效性!耶学习!
但后来我仔细观察,我的热情并没有因为一个简单的事实而被“完全压制”而是“完全熄灭”:你可以关闭断言。*
这听起来像是一场噩梦。如果我断言如果输入listOfStuff 是null,我不希望代码继续运行,那么我到底为什么要忽略该断言?听起来如果我正在调试一段生产代码并怀疑 listOfStuff 可能被错误地传递了 null 但没有看到任何日志文件证据表明该断言被触发,我不能相信 @987654327 @ 实际上得到了一个有效的值;我还必须考虑断言可能已完全关闭的可能性。
这假设我是调试代码的人。不熟悉断言的人可能会看到这一点并假设(相当合理地)如果断言消息没有出现在日志中,listOfStuff 就不是问题所在。如果您第一次遇到assert 是在野外,您是否会想到它可以完全关闭?毕竟,这不像是一个命令行选项可以让你禁用 try/catch 块。
所有这一切都让我想到了我的问题(这是一个问题,不是咆哮的借口!我保证!):
我错过了什么?
是否存在一些细微差别使得 Java 的 assert 实现比我认为的更有用?在某些情况下,从命令行启用/禁用它的能力真的非常有价值吗?当我设想在生产代码中使用它来代替像if (listOfStuff == null) barf(); 这样的语句时,我是否以某种方式误解了它?
我只是觉得这里有些重要的东西我没有得到。
*好吧,从技术上讲,它们实际上是默认关闭的;你必须不遗余力地打开它们。但是,您仍然可以将它们完全淘汰。
编辑: 请求启蒙,收到启蒙。
assert 首先是一个调试工具这一概念对我来说意义重大。
我仍然不同意在生产环境中应该禁用对重要私有方法的输入检查的概念,因为开发人员认为错误的输入是不可能的。以我的经验,成熟的生产代码是一个疯狂的、庞大的东西,多年来由具有不同技能水平的人针对快速变化的不同理智程度的需求而开发。即使错误的输入确实是不可能的,六个月后的一段草率的维护编码也可以改变这种情况。 The link gustafc provided(谢谢!)以这个为例:
assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;
在生产中禁用如此简单的检查让我觉得过于乐观了。但是,这是编码理念上的差异,而不是损坏的功能。
另外,我绝对可以看到这样的东西的价值:
assert reallyExpensiveSanityCheck(someObject) : someObject;
感谢所有花时间帮助我了解此功能的人;非常感谢。
【问题讨论】:
-
这看起来很像咆哮,根本不像是一个问题。
-
您曾经在 C 或 C++ 中使用过 ASSERT 吗?您是否曾希望弹指之间就能打开或关闭它们?
-
@Joachim:明白,但说真的,我是来寻求启迪的。这个特性在我看来确实是坏了——但这感觉就像说“我看不出我的代码有什么问题,因此编译器必须坏了!”,只是在更高的层次上。我真的觉得我错过了什么。如果你能建议我用一种方式来表达为什么这个功能让我觉得很糟糕,而不是让你觉得是咆哮,我在听。
-
您正在寻找的启示是:断言是为了帮助调试,而不是成为生产代码的一部分。
-
断言只不过是一个“可执行注释”。因此,对于代码的未来读者来说,它具有一些小的非零值。
标签: java language-features assert design-by-contract