断言什么时候应该保留在生产代码中?

发布于 2024-07-04 08:17:12 字数 1448 浏览 10 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

玻璃人 2024-07-11 08:17:12

如果您甚至考虑在生产中保留断言,那么您的想法可能是错误的。 断言的全部要点是您可以在生产中关闭它们,因为它们不是您的解决方案的一部分。 它们是一种开发工具,用于验证您的假设是否正确。 但当您投入生产时,您应该已经对自己的假设充满信心。

也就是说,在一种情况下,我会在生产中打开断言:如果我们在生产中遇到可重现的错误,而我们在测试环境中很难重现,那么在打开断言的情况下重现该错误可能会有所帮助在生产中,看看它们是否提供有用的信息。

一个更有趣的问题是:在测试阶段,什么时候关闭断言?

If you're even thinking of leaving assertions on in production, you're probably thinking about them wrong. The whole point of assertions is that you can turn them off in production, because they are not a part of your solution. They are a development tool, used to verify that your assumptions are correct. But the time you go into production, you should already have confidence in your assumptions.

That said, there is one case where I will turn assertions on in production: If we encounter a reproducible bug in production that we're having a hard time reproducing in a test environment, it may be helpful to reproduce the bug with assertions turned on in production, to see if they provide useful information.

A more interesting question is this: In your testing phase, when do you turn assertions off?

滴情不沾 2024-07-11 08:17:12

断言永远不应该保留在生产代码中。 如果一个特定的断言看起来可能在生产代码中有用,那么它不应该是一个断言; 它应该是运行时错误检查,即编码如下:if(condition!=expected) throw exception

“断言”一词的意思是“仅在开发时进行的检查,不会在现场执行”。

如果你开始认为断言可能会进入这个领域,那么你将不可避免地开始产生其他危险的想法,比如想知道任何给定的断言是否真的值得做出。 没有什么断言是不值得提出的。 你永远不应该问自己“我是否应该断言这一点?” 你应该只问自己“有什么我忘记断言的吗?”

Assertions should never stay in production code. If a particular assertion seems like it might be useful in production code, then it should not be an assertion; it should be a run time error check, i.e. something coded like this: if( condition != expected ) throw exception.

The term 'assertion' has come to mean "a development-time-only check which will not be performed on the field."

If you start thinking that assertions might make it to the field then you will inevitably also start making other dangerous thoughts, like wondering whether any given assertion is really worth making. There is no assertion which is not worth making. You should never be asking yourself "should I assert this or not?" You should only be asking yourself "Is there anything I forgot to assert?"

套路撩心 2024-07-11 08:17:12

除非分析表明这些断言导致了性能问题,否则我认为它们也应该保留在生产版本中。

然而,我认为这也要求您稍微优雅地处理断言失败。 例如,它们应该产生一般类型的对话框,其中包含(自动)向开发人员报告问题的选项,而不仅仅是退出或使程序崩溃。 另外,您应该小心,不要对您实际上允许但可能不喜欢或认为不需要的条件使用断言。 这些条件应该由代码的其他部分处理。

Unless profiling shows that the assertions are causing performance problems, I say they should stay in the production release as well.

However, I think this also requires that you handle assertion failures somewhat gracefully. For example, they should result in a general type of dialog with the option of (automatically) reporting the issue to the developers, and not just quit or crash the program. Also, you should be careful not to use assertions for conditions that you actually do allow, but possibly don't like or consider unwanted. Those conditions should be handled by other parts of the code.

时光与爱终年不遇 2024-07-11 08:17:12

在我的 C++ 中,我定义了 REQUIRE(x),它类似于 assert(x),只不过如果断言在发布版本中失败,它会抛出异常。

由于失败的断言表明存在错误,因此即使在发布版本中也应该认真对待。 当我的代码的性能很重要时,我通常会使用 REQUIRE() 来表示较高级别的代码,并使用 assert() 来表示必须快速运行的较低级别的代码。 如果失败情况可能是由第三方编写的代码传入的数据或文件损坏引起的,我也会使用 REQUIRE 而不是断言(最好我会专门设计代码,以便在文件损坏的情况下表现良好,但我们并不总是有时间这样做。)

他们说你不应该向最终用户显示这些断言消息,因为他们不会理解它们。 所以? 最终用户可能会向您发送一封电子邮件,其中包含屏幕截图或错误消息的一些文本,这有助于您进行调试。 如果用户只是说“它崩溃了”,您就无法修复它。 最好自动向自己发送断言失败消息,但这仅在以下情况下有效:(1) 软件在您控制/监视的服务器上运行,或者 (2) 用户可以访问互联网并且您可以获得他们的发送许可错误报告。

In my C++ I define REQUIRE(x) which is like assert(x) except that it throws an exception if the assertion fails in a release build.

Since a failed assertion indicates a bug, it should be treated seriously even in a Release build. When my code's performance matters, I will often use REQUIRE() for higher-level code and assert() for lower-level code that must run fast. I also use REQUIRE instead of assert if the failure condition may be caused by data passed in from code written by a third party, or by file corruption (optimally I would design the code specifically to be well behaved in case of file corruption, but we don't always have time to do that.)

They say you shouldn't show those assert messages to end-users because they won't understand them. So? End users may send you an email with a screen shot or some text of the error message, which helps you debug. If the user simply says "it crashed", you have no ability to fix it. It would be better to send the assertion-failure messages to yourself automatically, but that only works if (1) the software runs on a server you control/monitor or (2) the user has internet access and you can get their permission to send a bug report.

只是一片海 2024-07-11 08:17:12

如果您想保留它们,请用错误处理替换它们。 没有什么比程序消失更糟糕的了。 我认为将某些错误视为严重错误并没有什么错,但它们应该被引导到程序的一个部分,该部分可以通过收集数据、记录数据并通知用户您的应用程序出现了一些不需要的情况来处理它们,并且正在退出。

If you want to keep them replace them with error handling. Nothing worse than a program just disappearing. I see nothing wrong with treating certain errors as serious bugs, but they should be directed to a section of your program that is equipped to deal with them by collecting data, logging it, and informing the user that your app has had some unwanted condition and is exiting.

心在旅行 2024-07-11 08:17:12

如果它们像任何其他错误一样被处理,我不认为它有问题。 请记住,与其他语言一样,C 中的失败断言只会退出程序,而这对于生产系统通常是不够的。

有一些例外 - 例如,PHP 允许您为断言失败创建自定义处理程序,以便您可以显示自定义错误、执行详细日志记录等,而不仅仅是退出。

Provided they are handled just as any other error, I don't see a problem with it. Do bear in mind though that failed assertions in C, as with other languages, will just exit the program, and this isn't usually sufficient for production systems.

There are some exceptions - PHP, for instance, allows you to create a custom handler for assertion failures so that you can display custom errors, do detailed logging, etc. instead of just exiting.

江南烟雨〆相思醉 2024-07-11 08:17:12

我们的数据库服务器软件包含生产断言和调试断言。 调试断言就是这样——它们在生产代码中被删除。 仅当以下情况下才会发生生产断言:(a) 存在某些本不应该存在的条件,并且 (b) 无法从该条件中可靠地恢复。 生产断言表明软件中遇到了错误或发生了某种数据损坏。

由于这是一个数据库系统,并且我们正在存储潜在的企业关键数据,因此我们会尽一切努力避免数据损坏。 如果存在可能导致我们存储不正确数据的情况,我们会立即断言、回滚所有事务并停止服务器。

话虽如此,我们也尽量避免在性能关键例程中进行生产断言。

Our database server software contains both production and debug assertions. Debug assertions are just that -- they are removed in production code. Production assertions only happen if (a) some condition exists that should never exist and (b) it is not possible to reliably recover from this condition. A production assertion indicates that a bug in the software has been encountered or some kind of data corruption has occurred.

Since this is a database system and we are storing potentially enterprise-critical data, we do whatever we can to avoid corrupted data. If a condition exists that may cause us to store incorrect data, we immediately assert, rollback all transactions, and stop the server.

Having said that, we also try to avoid production assertions in performance-critical routines.

无声静候 2024-07-11 08:17:12

我将断言视为内联单元测试。 对于开发时的快速测试很有用,但最终应该重构这些断言,以便在单元测试中进行外部测试。

I see asserts as in-line unit tests. Useful for a quick test while developing, but ultimately those assertions should be refactored out to be tested externally in unit tests.

安人多梦 2024-07-11 08:17:12

假设一段代码正在生产中,并且它遇到了通常会触发的断言。 断言发现了一个bug! 但事实并非如此,因为断言已关闭。

那么现在会发生什么呢? 程序要么(1)在远离问题根源的地方以无信息的方式崩溃,要么(2)愉快地运行完成,可能会给出错误的结果。

这两种情况都不吸引人。 即使在生产中也使断言保持活动状态。

Suppose a piece of code is in production, and it hits an assertion that would normally be triggered. The assertion has found a bug! Except it hasn't, because the assertion is turned off.

So what happens now? Either the program will (1) crash in an uninformative way at a point further removed from the source of the problem, or (2) run merrily to completion, likely giving the wrong result.

Neither scenario is inviting. Leave assertions active even in production.

追风人 2024-07-11 08:17:12

我发现最好处理范围内的所有错误,并使用断言来假设我们断言是真的。

即,如果您的程序正在打开/读取/关闭一个文件,那么无法打开该文件就在范围内——这是一种真正的可能性,换句话说,忽略它是疏忽的。 因此,应该有与之相关的错误检查代码。

但是,假设您的 fopen() 被记录为始终返回有效的打开文件句柄。 您打开该文件,并将其传递给 readfile() 函数。

在这种情况下,readfile 函数可能根据其设计规范,几乎可以假设它将获得有效的文件 ptr。 因此,在如此简单的程序中添加针对负面情况的错误处理代码是浪费的。 然而,在继续执行之前,它至少应该以某种方式记录假设——以某种方式确保——事实确实如此。 它实际上不应该假设它总是有效,例如,如果它被错误地调用,或者它被复制/粘贴到其他程序中。

所以, readfile() { assert(fptr != NULL); .. } 在这种情况下是合适的,而成熟的错误处理则不然(忽略实际读取文件无论如何都需要一些错误处理系统的事实)。

是的,这些断言应该保留在生产代码中,除非绝对有必要禁用它们。 即使如此,您也应该仅在性能关键部分禁用它们。

I find it best to handle all errors that are in scope, and use assertions for assumptions that we're asserting ARE true.

i.e., if your program is opening/reading/closing a file, then not being able to open the file is in scope -- it's a real possibility, which would be negligent to ignore, in other words. So, that should have error-checking code associated with it.

However, let's say your fopen() is documented as always returning a valid, open file handle. You open the file, and pass it to your readfile() function.

That readfile function, in this context, and probably according to its design specification, can pretty much assume it's going to get a valid file ptr. So, it would be wasteful to add error-handling code for the negative case, in such a simple program. However, it should at least document the assumption, somehow -- ensure somehow --- that this is actually the case, before continuing its execution. It should not ACTUALLY assume that will always be valid, in case it's called incorrectly, or it's copy/pasted into some other program, for example.

So, readfile() { assert(fptr != NULL); .. } is appropriate in this case, whilst full-blown error handling is not (ignoring the fact that actually reading the file would require some error handling system anyway).

And yes, those assertions should stay in production code, unless its absolutely necessary to disable them. Even then, you should probably disable them only within performance-critical sections.

葬花如无物 2024-07-11 08:17:12

我很少将断言用于编译时类型检查以外的任何事情。 我会使用异常而不是断言,因为大多数语言都是为了处理它们而构建的。

我提供了一个示例

file = create-some-file();
_throwExceptionIf( file.exists() == false, "FILE DOES NOT EXIST");

应用

file = create-some-file();
ASSERT(file.exists());

程序如何处理断言? 我更喜欢使用旧的 try catch 方法来处理致命错误。

I rarely use assertions for anything other that compile time type checking. I would use an exception instead of an assertion just because most languages are built to handle them.

I offer an example

file = create-some-file();
_throwExceptionIf( file.exists() == false, "FILE DOES NOT EXIST");

against

file = create-some-file();
ASSERT(file.exists());

How would the application handle the assertion? I prefer the old try catch method of dealing with fatal errors.

断桥再见 2024-07-11 08:17:12

大多数时候,当我在java中使用断言(assert关键字)时,我会自动添加一些生产代码。 根据情况,它可以是一条日志消息、一个异常……或者什么都不是。

据我所知,您的所有断言在开发版本中都至关重要,而不是在生产版本中。 其中一些必须保留,另一些必须丢弃。

Most of the time, when i use assertion in java (the assert keyword) I automatically add some production codes after. According to the case, it can be a logging message, an exception... or nothing.

According to me, all your assertions are critical in dev release, not in production relase. Some of them must be kept, other must be discarded.

っ〆星空下的拥抱 2024-07-11 08:17:12

断言不是错误,不应被视为错误。 当抛出断言时,这意味着您的代码中或调用您的代码的代码中存在错误。

有几点需要避免在生产代码中启用断言:
1. 您不希望最终用户看到类似“ASSERTION failed MyPrivateClass.cpp line 147”的消息。最终用户不是您的 QA 工程师。
2. 断言可能会影响性能

然而,有一个强有力的理由保留断言:
断言可能会影响性能和时序,遗憾的是有时这很重要(特别是在嵌入式系统中)。

我倾向于投票支持在生产代码中保留断言,但确保这些断言打印输出不会暴露给最终用户。

~伊兹克

ASSERTIONS are not errors and should not be handled as errors. When an assertion is thrown, this means that there is a bug in your code or alternatively in the code calling your code.

There are a few points to avoid enabling assertions in production code:
1. You don't want your end user to see a message like "ASSERTION failed MyPrivateClass.cpp line 147. The end user is NOT you QA engineer.
2. ASSERTION might influence performance

However, there is one strong reason to leave assertions:
ASSERTION might influence performance and timing, and sadly this sometimes matter (especially in embedded systems).

I tend to vote for leaving the assertion on in production code but making sure that these assertions print outs are not exposed to end user.

~Yitzik

酒中人 2024-07-11 08:17:12

断言是错误的,纯粹且简单,因此应该像错误一样处理。

由于错误应该在发布模式下处理,所以你实际上不需要断言。

我认为断言的主要好处是条件中断 - 它们比钻取 VC 窗口来设置需要 1 行代码的东西要容易得多。

An assertion is error, pure and simple and therefore should be handled like one.

Since an error should be handled in release mode then you don't really need assertions.

The main benefit I see for assertions is a conditional break - they are much easier to setup than drilling through VC's windows to setup something that takes 1 line of code.

高速公鹿 2024-07-11 08:17:12

在生产代码中保持断言处于打开状态,除非您测量到关闭断言后程序运行速度明显加快。

如果不值得通过衡量来证明它更高效,那么就不值得为了性能赌博而牺牲清晰度。” - Steve McConnell 1993

http://c2.com/cgi/wiki?ShipWithAssertionsOn

Leave assertions turned on in production code, unless you have measured that the program runs significantly faster with them turned off.

if it's not worth measuring to prove it's more efficient, then it's not worth sacrificing clarity for a performance gamble." - Steve McConnell 1993

http://c2.com/cgi/wiki?ShipWithAssertionsOn

因为看清所以看轻 2024-07-11 08:17:12

请允许我引用 Steve McConnell 的《Code Complete》。 关于断言的部分是 8.2。

通常,您不希望用户在生产代码中看到断言消息; 断言主要供开发和维护期间使用。 断言通常在开发时编译到代码中,并在生产时从代码中编译出来。

然而,在同一部分的后面,给出了这个建议:

对于高度健壮的代码,断言然后处理错误。

我认为只要性能不是问题,就保留断言,而不是显示消息,而是将其写入日志文件。 我认为代码完整中也有该建议,但我现在找不到。

Allow me to quote Steve McConnell's Code Complete. The section on Assertions is 8.2.

Normally, you don't want users to see assertion messages in production code; assertions are primarily for use during development and maintenance. Assertions are normally compiled into the code at development time and compiled out of the code for production.

However, later in the same section, this advice is given:

For highly robust code, assert and then handle the error anyway.

I think that as long as performance is not an issue, leave the assertion in, but rather than display a message, have it write to a log file. I think that advice is also in Code Complete, but I'm not finding it right now.

我不吻晚风 2024-07-11 08:17:12

断言是不会过时的评论。 它们记录了哪些理论状态是预期的,哪些状态不应该发生。 如果代码发生更改,从而声明允许更改,开发人员很快就会收到通知并需要更新断言。

Assertions are comments that do not become outdated. They document which theoretical states are intended, and which states should not occur. If code is changed so states allowed change, the developer is soon informed and needs to update the assertion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文