我想知道在整个地方使用NSAssert是否是一个好习惯?这样做有什么好处?在哪些情况下使用它是个好主意?
Rob*_*ier 27
广泛使用NSAssert()不会将ObjC变成Eiffel,但只要你记住它实际上是如何实现的以及它正在做什么,它仍然是一个相当不错的实践.要记住的事情NSAssert():
NSAssert()默认情况下,Xcode 在"释放"模式下不会关闭.你必须记住添加NS_BLOCK_ASSERTIONS到GCC_PREPROCESSOR_DEFINITIONS你xcconfig.(你正在使用xcconfigs,对吗?)一个常见的问题是在nil会安静地工作的情况下断言非nil; 这可能意味着可以优雅恢复的事情发生现场崩溃.这与使用的NDEBUG宏无关assert(),并且您必须记住定义两者是否包含两种类型的断言.
如果您NSAssert()在发布模式下编译,那么当客户向您发送日志时,您无法指出问题发生的位置.我亲自包装NSAssert()自己的宏,即使在发布模式下也始终记录.
NSAssert()经常强迫重复的逻辑.考虑测试C++指针为NULL的情况.你使用NSAssert(),但你仍然需要使用一个简单的if()测试,以避免在现场崩溃.这种重复的代码可能成为bug的来源,我看到由于断言不再有效而导致代码失败.(幸运的是,这通常是在调试模式下!)我已经讨论了很多如何创建一个结合断言的宏if(),但是很难做到没有脆弱或难以理解代码.
由于上一个问题,我通常将" NSAssert(NO, ...)"放在一个else{}子句中,而不是在方法的顶部执行断言.这并不理想,因为它使合同远离方法签名(从而降低了其文件利益),但这是我在实践中发现的最有效的方法.
主要警告是副作用.如果你写:
NSAssert([self.navigationController popViewControllerAnimated:YES]!=nil,@"Something fails");
Run Code Online (Sandbox Code Playgroud)
popViewControllerAnimated:将在调试版本中执行,但不会在已剥离的发行版本中执行NSAssert().这意味着您的发行版本将与调试版本不同.
如果你足够小心,这个问题就会消失:
UIViewController* vc = [self.navigationController popViewControllerAnimated:YES];
NSAssert(vc!=nil,@"Something fails");
Run Code Online (Sandbox Code Playgroud)
调试.每当你编写代码时,你几乎总是在做假设.关于环境状态,参数值,局部变量和字段等的假设.通常,这些假设都是错误的(一位老同事给了我一个好的格言,"假设是所有fsckups的母亲") .
存在断言以验证您的假设,在您制作它们时.你有一个方法
void foo(int x)
{
…
}
Run Code Online (Sandbox Code Playgroud)
您知道并记录的只适用于x> 5?断言!
断言与单元测试和形式方法一起作为良好编码实践的一部分.虽然有些人可能认为全面的单元测试确保断言是多余的,但事实并非如此.例如,您可能会假设一种方法,例如,员工总是超过16岁且不到100岁 - 但目前代码并不需要这样.通过这些参数的单元测试将成功,但是稍后当您需要使用您的假设时,您将拥有通过测试的所有代码,但是错误.
我强烈推荐这篇文章
http://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html
正如文章所述,使用不是NSAssert的断言机制通常也是好事.例如:
https://github.com/hfossli/AGAssert
| 归档时间: |
|
| 查看次数: |
16748 次 |
| 最近记录: |