最后,我有一个问题要问Stack Overflow!:-)
主要目标是Java,但我认为它主要与语言无关:如果你没有本机断言,你可以随时模拟它.
我在一家销售一套用Java编写的软件的公司工作.代码很旧,至少可以追溯到Java 1.3,在某些地方,它显示......这是一个庞大的代码库,大约有两百万行,所以我们不能一次重构它.
最近,我们将最新版本从Java 1.4语法和JVM切换到Java 1.6,保守地使用了一些新功能,例如assert
(我们曾经使用过DEBUG.ASSERT宏 - 我知道assert
已经在1.4中引入但我们没有使用过它之前),泛型(只有打字的集合),foreach循环,枚举等.
尽管我已经阅读了几篇关于这个主题的文章,但我对assert的使用仍然有点青睐.然而,我看到的一些用法让我感到困惑,伤害了我的常识... ^ _ ^所以我想我应该问一些问题,看看我是否正确想要纠正的东西,或者它是否违背了常规做法.我很啰嗦,所以我大胆地提出问题,因为那些喜欢撇去东西的人.
作为参考,我在SO中搜索断言java并发现了一些有趣的线程,但显然没有完全重复.
如何避免java中的"!= null"语句?以及多少空检查就足够了?非常相关,因为很多断言我们只检查变量是否为空.在我们的代码中的某些地方,有空对象的用法(例如,返回new String[0]
)但并非总是如此.我们必须忍受这一点,至少是为了维护遗留代码.
Java声明中的一些好的答案也未得到充分利用.
哦,SO表示我应该何时使用Debug.Assert()?问题也是相关的(减少重复的好功能!).
首先,主要问题,今天引发了我的问题:
SubDocument aSubDoc = documents.GetAt( i ); assert( aSubDoc != null ); if ( aSubDoc.GetType() == GIS_DOC ) { continue; } assert( aSubDoc.GetDoc() != null ); ContentsInfo ci = (ContentsInfo) aSubDoc.GetDoc();
(是的,我们使用MS的C/C++样式/代码约定.我甚至喜欢它(来自相同的背景)!所以起诉我们.)
首先,assert()
表单来自DEBUG.ASSERT()
调用的转换.我不喜欢额外的括号,因为assert是一个语言结构,而不是(不再是,这里)一个函数调用.我也不喜欢return (foo);
:-)
接下来,断言不在这里测试不变量,它们更像是用来防止坏值.但正如我所理解的那样,它们在这里没用:assert会抛出一个异常,甚至没有记录伴随字符串,只有在断言被启用时才会抛出异常.所以,如果我们有-ea
选项,我们只是抛出一个断言而不是常规的NullPointerException.这看起来不是最重要的优势,因为无论如何我们都会在最高级别捕获未经检查的异常.
我是否正确地假设我们可以摆脱它们并与之共存(即让Java引发这种无法解决的异常)?(或者,当然,如果可能的话,测试空值,这在其他地方进行).
旁注:我应该在上面的片段中断言,我会针对ci值,而不是针对getter:即使大多数getter都经过优化/内联,我们也无法确定,所以我们应该避免调用它两次.
有人告诉我,在最后引用的线程中,公共方法应该使用针对参数值的测试(公共API的使用),而私有方法应该依赖于断言.好建议.
现在,这两种方法都必须检查另一个数据源:外部输入.IE浏览器.例如,来自用户,来自数据库,来自某个文件或来自网络的数据.
在我们的代码中,我看到了针对这些值的断言.我总是将这些更改为真正的测试,因此即使禁用断言它们也会起作用:这些不是不变量,必须正确处理.
我只看到一个可能的异常,其中输入应该是常量,例如填充了关系中使用的常量的数据库表:如果更改此表但相应的代码未更新,则程序将中断.
你看到其他例外吗?
我看到的另一个相对频繁的用法,似乎没问题:在交换机的默认情况下,或者在一系列else if
测试结束时 所有可能的值(这些情况可以追溯到我们使用枚举之前!),通常有一个assert false : "Unexpected value for stuff: " + stuff;
看似合法的我(这些情况不应该在生产中发生),你怎么看?(超出"无开关,使用OO"这些与此无关的建议).
最后,还有其他有用的用例或我在这里错过的讨厌的陷阱吗?(大概!)
最重要的规则是避免断言中的副作用.换句话说,代码应该与关闭断言的行为完全相同,因为断言打开时并没有失败(显然失败的断言会改变行为,因为它们会引发错误).
第二条规则是不使用断言进行基本检查.它们可以关闭(或者更准确地说,不能打开).对于非私有方法的参数检查,请使用IllegalArgumentException.
断言是可执行的假设.我使用断言表明我对该程序当前状态的看法.例如,像"我假设n在这里是正面的"或"我假设列表恰好有一个元素在这里"之类的东西.