assert作为标准代码的一部分使用而不是仅仅用于调试目的,是否存在性能或代码维护问题?
是
assert x >= 0, 'x is less than zero'
Run Code Online (Sandbox Code Playgroud)
好或坏比
if x < 0:
raise Exception, 'x is less than zero'
Run Code Online (Sandbox Code Playgroud)另外,有没有办法设置业务规则if x < 0 raise error,总是在没有try/except/finally这样的情况下进行检查,如果在整个代码中的任何时候x小于0都会引发错误,就像你assert x < 0在函数的开头设置一样,在函数内的任何地方哪里x变得少于0则引发异常?
有一个讨论,在comp.lang.c超过回事++.关于缓和与否的断言,这在C++中默认情况下只在调试中存在的构建,应保持在生产代码或没有.
显然,每个项目都是独特的,所以在这里我的问题是没有这么多是否断言应该保持,但在这情况下,这是值得推荐的/不是一个好主意.
通过断言,我的意思是:
我不一定在谈论C或C++.
我自己的观点是,如果你是程序员,但不拥有数据(大多数商业桌面应用程序就是这种情况),你应该保持它们,因为失败的断言显示了一个错误,你不应该去有bug,有可能破坏用户的数据.这会强制您在发货前进行强力测试,并使错误更加明显,从而更容易发现并修复.
你有什么看法/经验?
干杯,
卡尔
在此查看相关问题
回应和更新
嘿格雷厄姆,
断言是错误的,纯粹而简单,因此应该像一个一样处理.由于应该在发布模式下处理错误,因此您不需要断言.
这就是为什么我在谈论断言时更喜欢"bug"这个词.它使事情更加清晰.对我来说,"错误"这个词太模糊了.丢失的文件是错误,而不是错误,程序应该处理它.试图取消引用空指针是一个错误,程序应该承认有些东西闻起来像坏奶酪.
因此,您应该使用断言来测试指针,但是存在具有正常错误处理代码的文件.
稍微偏离主题,但讨论中的一个重点.
作为一个单挑,如果你的断言在失败时闯入调试器,为什么不呢.但是有很多原因导致文件不存在,完全不受代码控制:读/写权限,磁盘已满,USB设备已拔下等等.由于您无法控制它,我觉得断言是不是处理这个问题的正确方法.
卡尔
托马斯,
是的,我有代码完成,并且必须说我非常不同意该特定建议.
假设您的自定义内存分配器搞砸了,并将一些仍然被其他对象使用的内存归零.我碰巧将这个对象定期解除引用的指针归零,并且其中一个不变量是该指针永远不为空,并且你有几个断言以确保它保持这种状态.如果指针突然为空,你会怎么做?你只是if()围绕它,希望它有效吗?
请记住,我们在这里讨论产品代码,因此不会破坏调试器并检查本地状态.这是用户机器上的一个真正的错误.
卡尔
最后,我有一个问题要问Stack Overflow!:-)
主要目标是Java,但我认为它主要与语言无关:如果你没有本机断言,你可以随时模拟它.
我在一家销售一套用Java编写的软件的公司工作.代码很旧,至少可以追溯到Java 1.3,在某些地方,它显示......这是一个庞大的代码库,大约有两百万行,所以我们不能一次重构它.
最近,我们将最新版本从Java 1.4语法和JVM切换到Java 1.6,保守地使用了一些新功能,例如assert(我们曾经使用过DEBUG.ASSERT宏 - 我知道assert已经在1.4中引入但我们没有使用过它之前),泛型(只有打字的集合),foreach循环,枚举等.
尽管我已经阅读了几篇关于这个主题的文章,但我对assert的使用仍然有点青睐.然而,我看到的一些用法让我感到困惑,伤害了我的常识... ^ _ ^所以我想我应该问一些问题,看看我是否正确想要纠正的东西,或者它是否违背了常规做法.我很啰嗦,所以我大胆地提出问题,因为那些喜欢撇去东西的人.
作为参考,我在SO中搜索断言java并发现了一些有趣的线程,但显然没有完全重复.
new String[0])但并非总是如此.我们必须忍受这一点,至少是为了维护遗留代码.首先,主要问题,今天引发了我的问题:
SubDocument aSubDoc = documents.GetAt( i );
assert( aSubDoc != null );
if ( aSubDoc.GetType() == GIS_DOC )
{
continue;
}
assert( aSubDoc.GetDoc() != null );
ContentsInfo ci = (ContentsInfo) aSubDoc.GetDoc();
Run Code Online (Sandbox Code Playgroud)
(是的,我们使用MS的C/C++样式/代码约定.我甚至喜欢它(来自相同的背景)!所以起诉我们.)
首先,assert()表单来自DEBUG.ASSERT()调用的转换.我不喜欢额外的括号,因为assert是一个语言结构,而不是(不再是,这里)一个函数调用.我也不喜欢return (foo);:-) …