1
315
不,没有什么问题
也就是说,它应该用于在调试期间捕获“不可能发生”的情况,而不是正常的错误处理。
|
2
106
不,都不
断言用于进行健全性检查。如果不正确的话,应该杀死程序的东西。不用于验证或作为错误处理的替代。 |
3
61
按照这种逻辑,断点也是邪恶的。 断言应该用作调试辅助,而不是其他任何东西。”邪恶”是当你尝试使用它们时 相反 错误处理。 断言可以帮助您、程序员、检测和修复不存在的问题,并验证您的假设是否正确。 它们与错误处理无关,但不幸的是,一些程序员滥用它们,然后宣称它们是“邪恶的”。 |
4
39
我很喜欢使用断言。当我第一次构建应用程序时(也许对于新的域),我发现它非常有用。我没有做非常花哨的错误检查(我会考虑提前优化),而是快速编码,并添加了很多断言。在我了解了更多关于事情如何工作的知识之后,我重写并删除一些断言,然后更改它们以更好地处理错误。 由于断言的原因,我花费了大量的时间编写/调试程序。 我还注意到断言帮助我思考许多可能破坏程序的事情。 |
5
30
作为附加信息,Go提供了内置功能
|
6
29
它们应该用于检测程序中的错误。不错的用户输入。 如果使用正确,它们是 不 邪恶的。 |
7
13
这就产生了很多问题,我认为一个使断言的辩护变得混乱的问题是,它们通常基于论点检查。所以考虑一下这个不同的例子,当您可能使用断言时:
您对输入使用异常,因为您希望有时会得到错误的输入。您断言对列表进行排序是为了帮助您在算法中找到一个错误,根据定义,这是您所不期望的。断言只在调试版本中,所以即使检查很昂贵,您也不介意在每次调用例程时都这样做。 您仍然需要对生产代码进行单元测试,但这是一种不同的、互补的方法,可以确保代码是正确的。单元测试确保您的例程符合其接口,而断言是一种更细粒度的方法,可以确保您的实现正按照您期望的方式进行。 |
8
8
断言并不邪恶,但很容易被滥用。我同意“断言经常被用作拐杖,以避免考虑正确的错误处理和报告”。我经常看到这个。 就我个人而言,我喜欢使用断言,因为它们记录了我在编写代码时可能做出的假设。如果在维护代码的同时打破了这些假设,则可以在测试期间检测到问题。但是,在进行生产构建(即,使用ifdefs)时,我确实要从代码中剥离出每个断言。通过剥离生产构建中的断言,我消除了任何人将它们作为拐杖滥用的风险。 断言还有另一个问题。断言只在运行时检查。但通常情况下,您希望执行的检查可能是在编译时执行的。最好在编译时检测一个问题。对于C++程序员来说,Boost提供了BooStyStistAsAsHyt,允许您这样做。对于C程序员,本文( link text )描述一种可用于在编译时执行断言的技术。 总之,我遵循的经验法则是:不要在生产构建中使用断言,如果可能的话,只对编译时无法验证的东西使用断言(即必须在运行时检查)。 |
9
5
我承认在考虑错误报告时使用了断言。但是,这并不能说明它们在正确使用时非常有用。 如果你想遵循“早点崩溃”的原则,它们尤其有用。例如,假设您正在实现一个引用计数机制。在代码的某些位置,您知道refcount应该是零或一。另外,假设refcount错误,程序不会立即崩溃,但是在下一个消息循环期间,很难找出出错的原因。断言将有助于检测更接近其来源的错误。 |
10
5
我更喜欢避免在调试和发布中执行不同操作的代码。 但是,在条件下中断调试器并拥有所有文件/行信息非常有用,这也是精确表达式和精确值。 断言“只在调试中评估条件”可能是一种性能优化,因此,只有在0.0001%的程序中才有用,因为人们知道他们在做什么。在所有其他情况下,这是有害的,因为表达式实际上可能改变程序的状态:
我们已经开发了一组断言宏,它将引发异常,并在调试和发布版本中执行该操作。例如,
|
11
5
我非常不喜欢断言。但我不会说他们是邪恶的。 基本上,断言和未检查的异常一样,唯一的异常是断言(通常)不应该为最终产品保留。 如果您在调试和构建系统时为自己构建了一个安全网,为什么您会拒绝为您的客户、支持服务台或任何可以使用您当前构建的软件的人提供此安全网?只对断言和异常情况使用异常。通过创建一个适当的异常层次结构,您将能够很快地分辨出其中一个。除此之外,断言仍然存在,并且可以在失败时提供有价值的信息,否则将丢失。 因此,我完全理解go的创建者,通过完全删除断言并强制程序员使用异常来处理这种情况。对此有一个简单的解释,例外只是一个更好的机制,为什么要坚持古老的断言? |
12
3
简短回答:不,我相信断言是有用的 |
13
3
我最近开始在代码中添加一些断言,我就是这样做的: 我将代码分为边界代码和内部代码。边界代码是处理用户输入、读取文件和从网络获取数据的代码。在这段代码中,我在一个循环中请求输入,该循环仅在输入有效时(在交互用户输入的情况下)退出,或者在文件/网络不可恢复的损坏数据的情况下抛出异常。 内部代码就是一切。例如,在类中设置变量的函数可以定义为
从网络获取输入的函数可能如下所示:
这给了我两层支票。任何在运行时确定数据的地方都会得到异常或立即的错误处理。但是,额外的入住
这似乎符合我在一些地方读到的内容,即在一个运行良好的程序中断言不可能被违反,而异常情况应该适用于仍然可能出现的异常和错误情况。因为从理论上讲,我正在验证所有输入,所以不可能触发我的断言。如果是,我的程序是错误的。 |
14
1
另一方面,很容易被滥用
正确的版本如下:
所以…从长远来看…在大局中…我必须同意
|
15
1
因此,作为语言设计者,他们更应该看到,可以通过更小的输入来完成正确的错误处理。排除断言,因为您的异常机制是verbose而不是解决方案。哦,等等,Go也没有例外。太糟糕了:) |
16
1
当我看到这一点时,我觉得自己像是在踢作者的头。 我一直在代码中使用断言,并最终在编写更多代码时将它们全部替换。当我没有编写所需的逻辑时,我使用它们,当我遇到代码时,我希望得到警告,而不是编写一个异常,当项目接近完成时,它将被删除。
异常也更容易与我不喜欢的生产代码混合。断言比
|
17
1
我对这些答案的问题是,辩护断言没有人明确指出它与常规断言的不同之处。 致命错误 以及为什么断言不能是 例外 . 现在,有了这句话,如果这个例外永远不会被发现呢?这是否使它成为一个命名断言?而且,为什么你会想要在语言中施加一个可以引发一个异常的限制,这个异常是/没有/可以处理的? |
18
1
是的,断言是邪恶的。 它们经常被用于应该使用正确错误处理的地方。从一开始就习惯于写正确的生产质量错误处理! 通常它们会妨碍编写单元测试(除非您编写了一个与测试工具交互的自定义断言)。这通常是因为在应该使用正确错误处理的地方使用它们。 大多数情况下,它们是从发布版本中编译出来的,这意味着当您运行实际发布的代码时,它们的“测试”都不可用;考虑到在多线程情况下,最糟糕的问题通常只出现在发布代码中,这可能是很糟糕的。 有时它们是破坏设计的拐杖;也就是说,代码的设计允许用户以不应该调用的方式调用它,断言“阻止”了这一点。修复设计! 我在2005年的博客上写了更多这方面的内容,这里是: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html |
19
1
如果您所说的断言意味着程序呕吐然后存在,那么断言可能非常糟糕。这并不是说他们是 总是 使用错误的东西,它们是一个很容易被滥用的结构。他们还有许多更好的选择。像这样的事情是被称为邪恶的好候选人。 例如,第三方模块(或任何真正的模块)几乎不应该退出调用程序。这并不能让调用程序的程序员控制此时程序应该承担的风险。在许多情况下,数据非常重要,即使保存损坏的数据也比丢失数据要好。断言会强制您丢失数据。 断言的一些替代方法:
一些参考文献:
即使提倡断言的人也认为他们应该只用于发展和 不 生产中:
这个人说,当模块有可能损坏在引发异常后仍然存在的数据时,应该使用断言: http://www.advogato.org/article/949.html . 这当然是一个合理的观点,但是,外部模块应该 从未 规定损坏的数据对调用程序有多重要(通过退出“for”它们)。处理这种情况的正确方法是抛出一个异常,它使程序现在可能处于不一致的状态。而且,由于好的程序主要由模块组成(在主可执行文件中有一些粘合代码),断言几乎总是错误的。 |
20
0
与其说是邪恶,不如说是适得其反。永久性错误检查和调试之间有一个分离。断言使人们认为所有调试都应该是永久的,并且在经常使用时会导致大量的可读性问题。永久性错误处理应该比需要的地方更好,因为断言会导致自己的错误,这是一个相当可疑的实践。 |
21
0
我从不使用assert(),示例通常显示如下内容:
这很糟糕,我从来没有这样做,如果我的游戏是分配一堆怪物呢?为什么我要让游戏崩溃,而你应该优雅地处理错误,所以做如下的事情:
|
J.Yarovich · 我可以在日志文件中写入断言消息吗? 7 年前 |
Leedehai · C++:汇编代码包含断言结果 7 年前 |
seldon · 节点。js断言。使用异步函数抛出(Promises) 8 年前 |
user2738698 · 是否可以检查pcap中是否激活了接口? 9 年前 |