为什么我应该使用断言?

发布于 2024-07-26 23:10:43 字数 304 浏览 5 评论 0原文

我从来没有想过断言——为什么要使用它们?

我的意思是,假设我是一名方程式赛车手,所有的断言都是安全带、头盔等。

测试(调试中)都没有问题,但现在我们想做赛车(发布)! 因为测试时没有问题,我们是否应该放弃所有安全性?

我永远不会删除它们。 我认为大多数声称删除了与断言类似的东西的人从未分析过他们的代码,或者断言被绝对取代了。 我从未见过任何真正的性能优势,尤其是关于 80 / 20 规则。

那么,我是否错过了要点,或者有人可以告诉我,为什么我应该使用断言? 顺便说一句,我正在使用单元测试。

I never got the idea of asserts -- why should you ever use them?

I mean, let's say I were a formula driver and all the asserts were things like security belt, helmet, etc.

The tests (in debug) were all okay, but now we want to do racing (release)!
Should we drop all security, because there were no issues while testing?

I will never ever remove them. I think most of the guys that claim that removing something comparable to asserts never profiled their code or the asserts were absolute displaced.
I've never seen any real performance advantage especially regarding the 80 / 20 rule.

So, am I missing the point somehow, or could anybody tell me, why I should use asserts?
By the way, I'm using unit tests.

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

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

发布评论

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

评论(19

我只土不豪 2024-08-02 23:10:43

首先,性能差异可能非常巨大。 在一个项目中,我们的断言实际上导致了 3 倍的速度减慢。 但他们帮助我们发现了一些非常讨厌的错误。

这正是重点。

断言可以帮助您捕获错误。 因为它们在发布版本中被删除,所以我们可以放入大量它们,而不必担心性能。 如果你不在那里对任何失败的断言采取实际行动,它们就会变得毫无价值,所以我们不妨删除它们。

即使捕获错误并抛出异常也不是真正的解决方案。 程序逻辑有缺陷,即使我们处理了异常,程序仍然是坏的。

断言基本上可以归结为“为什么要费心去捕捉你无法处理的错误呢?”

在开发过程中必须捕获一些错误。 如果它们通过了测试并进入了客户使用的发布版本,那么该程序就被破坏了,并且任何运行时错误检查都无法修复它。

我从来没有想过断言——为什么要使用它们?

我的意思是,假设我是一名方程式赛车手,所有的主张都是安全带、头盔等。

是的,这是一个使用断言的好例子。 这些是在运行时实际上可能出错的事情,需要检查。 您的一级方程式赛车手可能会忘记一些安全预防措施,如果他忘记了,我们希望在有人受伤之前停止整个事情。

但是检查发动机是否已安装呢? 我们需要在比赛期间检查这一点吗?

当然不是。 如果我们在没有引擎的情况下参加比赛,我们就完蛋了,即使我们检测到错误,也为时已晚。

相反,这是一个在开发过程中必须捕获的错误,或者根本不捕获。 如果设计者忘记在他们的汽车中安装发动机,他们需要在开发过程中检测到这个错误。 这是一个断言。 开发的时候跟开发人员有关系,但是开发之后,这个错误一定不能存在,如果存在了,我们也无能为力。

这基本上就是区别。 异常是通过处理可以处理的错误来帮助用户的。

断言可以帮助您,提醒您绝对不能发生的错误,这些错误必须在产品发货之前修复。 错误不依赖于用户输入,而是依赖于代码执行其应该执行的操作。

四的平方根绝不能等于三。 这个错误根本不可能发生。 如果它确实发生,那么你的程序逻辑就被破坏了。 无论我们对它进行多少错误处理,它都是在开发过程中必须捕获的东西,或者根本不捕获。 如果我们使用异常处理来检查这个错误并处理它,那么异常会做什么? 告诉用户“该程序已从根本上损坏。永远不要使用它”?

开发人员的一封电子邮件就可以实现这一目标。 为什么要把它构建到程序代码中呢? 这是一个绝对不能发生的问题的例子。 如果确实如此,我们就必须返回并修复程序。 不可能有其他形式的错误处理。

可能出现一些错误,例如无法打开文件进行读取。 尽管如果发生的话可能是一件坏事,但我们必须接受它可能发生。 所以如果有的话我们需要处理。

断言用于捕获不可能发生的错误。

First, the performance difference can be huge. In one project our asserts literally caused a 3x slowdown. But they helped us uncover some really pesky bugs.

Which is exactly the point.

Asserts are there to help you catch bugs. And because they are removed in release builds, we can afford to put a lot of them in without worrying about performance. If you're not there to actually act on any failed assertions, they become worthless, so we might as well remove them.

Even catching the error and throwing an exception isn't really a solution. The program logic is flawed, and even if we handle the exception, the program is still broken.

What asserts basically boil down to is "Why bother catching errors you can't handle?"

Some errors must be caught during development. If they slip past testing and into the release build used by a customer, the program is just broken, and no amount of runtime error-checking is going to fix it.

I never got the idea of asserts -- why should you ever use them?

I mean, let's say I were a formula driver and all the asserts were things like security belt, helmet, etc.

Yes, that's a good example of when not to use an assert. These are things that might actually go wrong at runtime, and which need to be checked. Your formula one driver might forget some security precaution, and if he does, we want to halt the whole thing before anyone gets hurt.

But what about the check to see that the engine is installed? Do we need to check that during the race?

Of course not. If we get into the race without an engine, we're screwed, and even if we detect the error, it's too late to do anything about it.

Instead, this is an error that must be caught during development or not at all. If the designers forget to put an engine in their car, they need to detect this error during development. That's an assert. It's relevant to the developers during development, but afterwards, the error must not exist, and if it does, there's nothing we can do.

That's basically the difference. An exception is there to help the user, by handling errors that can be handled.

An assert is there to help you, by alerting you to errors that must never occur in the first place, that must be fixed before the product can be shipped. Errors that do not depend on user input, but on your code doing what it is supposed to do.

The square root of four must never evaluate to three. The error is simply impossible. If it does occur, your program logic is just broken. It doesn't matter how much error handling we wrap around it, it's something that must be caught during development or not at all. If we used exception handling to check for this error and handle it, what is the exception going to do? Tell the user "the program is fundamentally broken. Don't ever use it"?

An email from the developer could have achieved that. Why bother building it into the program code? That's an example of a problem that simply must not occur. If it does, we have to go back and fix the program. No other form of error handling is possible.

But some errors, like being unable to open a file for reading, are possible. Even though it might be a bad thing if it happens, we have to accept that it can happen. So we need to handle it if it does.

Asserts are for catching the errors that can't possibly happen.

皓月长歌 2024-08-02 23:10:43

Andrew Koenig 曾经有一个 关于在运输代码中使用异常和断言的良好哲学讨论。 最后,当程序处于无法修复的损坏状态时,您要防止做出疯狂的事情

因此,我相信,当
程序发现了一些东西
其内在是无可辩驳的错误
状态,最好终止于
一次,而不是给它的调用者
有机会假装
没什么问题。

如果你愿意,我认为例外
应保留用于以下情况
可以做某事
捕获异常后明智。
当你发现某种状况时,你
认为不可能,很难
多说可能发生的事情
之后。

Andrew Koenig used to have a good philosophical discussion over the usage of exceptions and assertions in shipping code. In the end, you're guarding against doing wild things when the program is in an irreparably broken state.

I believe, therefore, that when a
program discovers something that is
irrefutably wrong with its internal
state, it is better off terminating at
once, rather than giving its caller
the opportunity to pretend that
nothing is wrong.

If you like, I think that exceptions
should be reserved for situations in
which it is possible to do something
sensible after catching the exception.
When you discover a condition that you
thought was impossible, it's hard to
say much about what might happen
afterward.

垂暮老矣 2024-08-02 23:10:43

来自代码完整 2:“对预期发生的情况使用错误处理;对不应该发生的情况使用断言。”

一个常见的例子是在除法之前检查分母是否为零。

您应该从生产代码中删除断言。 它们在开发过程中可以帮助您发现错误。

单元测试不能替代断言。

From Code Complete 2: "Use error-handling for conditions you expect to occur; use assertions for conditions that should never occur."

A commonly-cited example is checking for zero in the denominator before a division.

You're expected to strip the assertions out of production code. They are in there during development to help you catch mistakes.

Unit tests are not a replacement for assertions.

甲如呢乙后呢 2024-08-02 23:10:43

因为它们使调试更容易。

调试的耗时部分是将问题从您首先注意到的症状追溯到代码中的错误。 写得好的断言将使您注意到的症状更接近实际的代码问题。

一个非常简单的例子是一个错误,您索引超过数组末尾并导致内存损坏,最终导致崩溃。 从崩溃追溯到有问题的索引操作可能需要很长时间。 但是,如果在检查索引的索引操作旁边有一个断言,那么您的程序将在错误旁边失败,因此您将能够快速找到问题。

Because they make debugging easier.

The time consuming part of debugging is tracing a problem from the symptom you first notice back to the error in the code. Well written assertions will make the symptom you notice much closer to the actual code problem.

A very simple example would be a bug where you index past the end of an array and cause memory corruption which eventually causes a crash. It can take a long time to trace back from the crash to the offending index operation. However, if you have an assertion next to that index operation that checks your index, then your program will fail right next to the error, so you'll be able to find the problem quickly.

神妖 2024-08-02 23:10:43

这是一个有争议的话题。 许多人,比如我自己,实际上更喜欢将它们保留在生产代码中。 如果你的程序无论如何都会陷入困境,你最好在那里有断言,这样你的客户至少可以给你行号和文件名(或者你配置断言要执行的任何信息或操作)。 如果您忽略了该断言,则客户只能向您报告“它崩溃了”。

这意味着您可能不应该在断言检查中执行昂贵的操作,或者至少分析一下它们是否会导致性能问题。

It's a controversial subject. Many people, like myself, do actually prefer to leave them on in production code. If your program is going to go into the weeds anyway, you might as well have the assertion in there so your customer can at least give you the line number and filename (or whatever information or action you configure the assert to do). If you left the assertion out, all the customer could report to you was "it crashed".

This means you probably should not do expensive operations in your assert checks, or at least profile to see if they are going to cause performance problems.

还不是爱你 2024-08-02 23:10:43

它们使您能够测试您的假设。 例如,假设您想计算速度。 您可能想要断言您的计算速度低于光速。

断言是为了开发,以确保你不会搞砸。

They enable you to test your assumptions. For example, let's say that you wanted to calculate speed. You would probably want to assert that your calculation is less than the speed of light.

Assertions are for development, to make sure you don't mess up.

许久 2024-08-02 23:10:43

只是当您不需要时不要使用断言。 不使用它并没有什么错。

仅当调试模式下的测试用例实际命中断言时,断言才有用。 很多时候它根本不会成功,这取决于测试用例的质量。 当你尝试验证一个假设时,会使用断言,这样你就得到了你所要求的,在测试过程中你几乎不会打破你的假设。 这就是为什么你首先假设它不是。 然而,有无数的“预期不可能”的情况在调试过程中确实没有达到您的断言,但在禁用断言的生产中仍然以某种方式达到。 如果您在调试期间依赖断言,那么您很可能最终会在生产中发生一些意外的事情,甚至您的断言也没有捕获。

您的程序应该以战略方式进行设计,以便即使发生意外情况或您的测试用例未涵盖,问题仍能以定义的方式处理,或产生有意义的诊断信息。

您可以使用断言来帮助排除故障,但如果您想从一开始就防止问题发生,那么它就没有帮助。 原因是,如果您认为生产中不会发生某个利基问题(您在生产中禁用断言),则无法预防或处理该问题。 好的软件应该捕获明显的错误(断言有帮助),以及小众错误(断言可能没有帮助)。

许多人会告诉您断言应该做什么的标准版本。 什么断言有好处等等。但是如果它真的有帮助或没有帮助,请根据您自己的经验来证明。 断言不是科学证明的或黄金法则,它只是许多人的实践。 您应自行决定采用或不采用。

Just don't use Assertions when you don't want. There is nothing wrong not to use it.

Assertion is only helpful when a test case in debug mode actually hit it. Many times it doesn't hit at all, depends on quality of your test cases. Assertion is used when you try to verify an assumption, so you got what you asked for, you hardly break your assumption during test. That's why you assume it in first place isn't it. Yet there are endless number of "expected impossible" cases that really don't hit your assertion during debug, but somehow still hit in production which have assertion disabled. If you rely on assertion during debug then you most likely end up having some unexpected thing happen in production that even your assertion didn't catch.

Your program should be designed in a strategic way, so that even unexpected matter happen or your test cases didn't cover, a problem is still handled in a defined way, or produce meaningful diagnostic info.

You can use assertion to help troubleshooting, but it is not helpful if you want to prevent problem from happening in first place. The reason is that you can't prevent or handle a niche problem if you assume it won't happen in production (you disable assertion in Production). Good software should catch obvious errors (assertion helps), as well as niche errors (assertion probably won't help).

Many people will tell you a standard version of what is assertion supposed to do. What assertion is good for etc. But please justify by your own experience if it is really helpful or not. Assertion is not scientific proven or golden rule, it is just a practice of many people. You should decide to adopt it or not by yourself.

清眉祭 2024-08-02 23:10:43

从您的帖子来看,听起来您并不不同意使用断言的想法,而是不同意在调试中使用断言而不是在生产中激活它们的想法。

这样做的原因是,在调试时,您可能希望进程灾难性地失败——即抛出异常并退出,以便解决错误。 在生产中,这可能会影响您的整个系统,并且错误情况可能仅在极少数情况下发生。 因此,在生产中您可能希望记录错误,但保持进程运行。

使用断言可以让您更改调试和发布之间的行为。

我同意你的观点,断言不应该仅仅在生产代码中被静音——许多错误在测试环境中不会暴露,并且了解断言何时在生产中失败非常重要。

From your post, it sounds like you are not disagreeing with the idea of using assertions, but rather the idea of having assertions in debug and not having them active in production.

The reason for this is that when debugging, you might want the process to fail catastrophically -- i.e. throw an exception and quit, so that the error can be addressed. In production, this could affect your entire system, and the error condition could occur only for a very few cases. So, in production you would probably want to log the error, but keep the process running.

Using assertions lets you change the behavior between debug and release.

I agree with you that the assertions should not just be silenced in production code -- many errors are not exposed in test environments and it is important to know when assertions fail in production.

ぇ气 2024-08-02 23:10:43

我认为重构时断言是无价的。 如果您想用 Algorithm2() 替换 alogrihm1(),您可以同时使用它们并断言结果相等。 然后,您可以逐步淘汰算法 1()

断言也适用于您可能快速做出的一些更改,但在系统状态的上下文中不太确定。 为您所做的假设设置断言,将很快帮助您指出问题(如果有)。

是否应该在发布中通过使用宏等来剥离断言是有争议的,但这就是我迄今为止所从事的项目中所做的事情。

Assertions are invaluable while refactoring I think. If you want to replace alogrihm1() with algorithm2(), you could have them both and assert on the results being equal. You can then gradually phase out the algorithm1()

Asserts are also good for some changes that you might make quickly, but are not too sure of in the context of the state of the system. Setting up asserts for the assumptions you make, would quickly help you to point out the problem, if any.

It is debatable whether asserts should be stripped via using macros or the like in release, but that's what has been done in the projects I have worked on so far.

独自唱情﹋歌 2024-08-02 23:10:43

在我参与过的许多项目中,断言是使用自定义宏完成的,该宏在调试和发布中具有不同的行为。

在调试中,如果条件为假,则调试器将在代码中的该点启动。

在Release中,错误被写入日志文件,向用户发出警告,然后系统尝试保存未保存的数据。 由于处于未知状态,这可能会失败,但值得尝试。

In many project I've worked in, assertions were done with a custom macro that had different behaviour in Debug and Release.

In Debug, if the condition is false the debugger is started at that point in the code.

In Release, the error is written to a log file, a warning given to the user, and then the system attempts to save unsaved data. Being in an unknown state, this may fail, but it's worth trying.

痴情换悲伤 2024-08-02 23:10:43

在完整的代码中,有一个部分说了类似的话。 每次你写一个 if 而没有其他任何东西时,你可能会遗漏一些东西。

就像这段代码

int i = 1
i = i++ 

一般程序员永远不会想到如果后面的代码中 i 为负数会发生什么。
您的代码有可能会产生溢出,并且像 java 这样的语言将从 max int 跳转到 min int,并且您会得到一个非常大的负数。 这都是你平常说的情况。 呃,这永远不会发生。 但如果发生这种情况,你的程序会做什么呢? 因此,如果您知道有一些您认为永远不会发生的事情,请测试它或反对它,并在永远不会发生的 else 子句中放置一个断言 false,而不是不编写 else 语句。
这样,当您不确定程序在做什么时,您的程序应该完全崩溃。 在生产代码中应该有一些不同于崩溃的东西,比如通知用户、维护者然后退出。

断言的另一个用途是契约驱动设计。 您与接口指定合同,并根据您在程序中的位置断言您的输入,但更重要的是您断言输出两个。

我同意你的观点,生产代码中禁用的断言会使断言变得毫无用处。 在我看来,在 java 虚拟机的情况下默认断言关闭是一种危险。

In Code complete is a section that says something like. Every time you write an if without any else you are maybe missing something.

It is like this code

int i = 1
i = i++ 

The common programmer will never think about what happens if i is negative in later code.
There is the slightly chance of your code producing an overflow and languages like java will jump from max int to min int and you get a very big negative number. This are all the cases you normally say. Uh this will never ever happen. But what is your program doing if it happens? So if you know that there is something that you think will never happen test for it or against it and put an assert false in the else clause that will never happen instead of don't program the else statement.
In this way your program should crash completely in the moment you aren't sure any more what it is doing. In production code there should be something different from rather crashing something like informing the user, the maintainer and then exiting.

Another use of assertions is contract driven design. You specify an contract with your interface and depending on your place in the program you assert your input but much more importing you are asserting your output two.

I agree with you that disabled assertions in production code make assertions rather useless. And the default assertions off in case of the java vm is a hazard in my opinion.

魔法少女 2024-08-02 23:10:43

我编写的代码中,断言在启用时明显影响性能。 例如,检查图形代码在紧密循环中使用的数学函数的前置条件和后置条件(平方根函数对其结果进行平方并将其与输入进行比较等)。 当然,它大约是几个百分点,但我已经编写了需要这几个百分点的代码。

更重要的是,我编写的代码中的断言对代码的大小造成了数十个百分点的差异。 当内存占用成为问题时,发布代码中的断言可能是一种不可接受的浪费。

I've written code where the assertions demonstrably affected performance when enabled. Checking the pre- and post-conditions of maths functions used in tight loops by your graphics code, for example (square root function squares its result and compares it against the input, etc). Sure, it's on the order of a few percentage points, but I've written code that needed those few points.

More importantly, I've written code where the assertions made a tens-of-percentage-points difference to the size of the code. When memory footprint is an issue, asserts in release code are probably an unacceptable extravagance.

九歌凝 2024-08-02 23:10:43

断言只能用于检查开发过程中发布过程中不需要的条件。

这是一个非常简单的示例,说明如何在开发中使用断言。

A(char* p)
{
    if(p == NULL)
        throw exception;

    B(p);
    C(p);

}

B(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

C(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

D(char* p)
{
    assert(p != NULL);
    do stuff;
}

而不是调用“if(p == NULL) throw exception;” 5 次,您只需调用一次,因此在输入 B()、C() 和 D() 时您就已经知道它不为 NULL。 否则,断言将在开发阶段退出,因为您“更改了代码!” 不是因为“用户的输入”。

这可以使代码在发布版本中运行得更快,因为您所要做的就是使用“-DNDEBUG”调用 gcc,因此所有断言都不会被编译,并且所有“不必要的检查”都将在可执行文件中删除。

Asserts should only be used to check conditions during development that are not needed during release.

Here is a really simple example of how assertion can be used in development.

A(char* p)
{
    if(p == NULL)
        throw exception;

    B(p);
    C(p);

}

B(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

C(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

D(char* p)
{
    assert(p != NULL);
    do stuff;
}

Instead of calling "if(p == NULL) throw exception;" 5 times, you just call it once so you already know it's not NULL upon entering B(), C(), and D(). Otherwise, an assertion will exit in the development phase because you "changed the code!" not because of a "user's input".

This can make the code run a lot faster in the release version because all you have to do is invoke gcc with "-DNDEBUG" so all of the assertions will not be compiled and all the "unnecessary checks" will be removed in the executable.

坦然微笑 2024-08-02 23:10:43

我主要用它来进行开发过程中的测试。 例如, 这是冒烟测试我的 utf-8 库 每当我对库代码进行更改时,我都会运行测试,如果引入错误,则会触发断言。 当然,我可以使用成熟的单元测试框架,但就我的目的而言,断言就可以了。

I use it mostly for tests during development. For instance, here is the smoke test of my utf-8 library Whenever I make a change in the library code I run the tests and if a bug is introduced an assert will trigger. Of course, I could have used a full-blown unit test framework, but for my purposes asserts are just fine.

挖鼻大婶 2024-08-02 23:10:43

忍不住引用“不可或缺的加尔文和霍布斯”第 14 页。 180:

在下这样陡峭的山坡之前,应该先对雪橇进行安全检查。
对。
安全带 ? 没有。
信号? 没有。
刹车? 无。
操舵 ? 没有。
呼呼呼

Can't resist quoting "The indispensable Calvin and Hobbes" p. 180:

Before going down a steep hill like this, one should always give his sled a safety check.
Right.
Seat belts ? None.
Signals ? None.
Brakes ? None.
Steering ? None.
WHEEEEEE

×纯※雪 2024-08-02 23:10:43

当你做这样的事情时应该使用断言

a = set()
a.add('hello')
assert 'hello' in a

a = 1;
assert a == 1; // if ram corruption happened and flipped the bit, this is the time to assert

至于异常,这是你以编程方式处理的事情:

while True:
  try:
    data = open('sample.file').read()
    break // successfully read
  except IOError:
    // disk read fail from time to time.. so retry
    pass

大多数时候,当断言发生时重新启动应用程序会更安全,因为你不想处理不可能的情况。
但是当预期的情况发生时(预期的错误(大多数时候来自黑盒客户端、网络调用等),应该使用异常。

Assertion should be used when you do something like this

a = set()
a.add('hello')
assert 'hello' in a

or

a = 1;
assert a == 1; // if ram corruption happened and flipped the bit, this is the time to assert

As for exceptions, it's something you programmatically deal with:

while True:
  try:
    data = open('sample.file').read()
    break // successfully read
  except IOError:
    // disk read fail from time to time.. so retry
    pass

Most of the time it's safer to restart your application when assert happens, because you don't want to deal with impossible cases.
But when the expected case happens (expected errors (most of the time from black-box clients, network calls, etc..) the exceptions should be used.

绿萝 2024-08-02 23:10:43

断言应该用于预测程序员使用 API/函数/类/任何内容的方式中的错误。 这些错误需要在调试时快速修复。

对于其他一切,抛出异常。

Assertion should be used for anticipating error in the way a programmer is using an API/function/class/whatever. These bugs need to be fixed quickly at debug time.

For everything else, throw an exception.

邮友 2024-08-02 23:10:43

对于这个问题的其他答案

assert() 宏用于测试条件或假设
不应该出现在程序中。 例如,数组索引应该
总是> 0.另一个假设可以是2+2 == 3+1。

因此,使用assert()我们可以测试这样的假设,只要它们
评估为true,我们的程序正常运行。 当它们为假时,
程序终止。

更多这里
https://www.softwaretestinghelp.com/assert-in-cpp/

For other answers to this question

assert() macro is used to test the conditions or assumptions that
should not occur in a program. For example, the array index should
always be > 0. Another assumption can be 2+2 == 3+1.

So using assert () we can test such assumptions and as long as they
evaluate to true, our program runs normally. When they are false, the
program is terminated.

more here
https://www.softwaretestinghelp.com/assert-in-cpp/

淡淡的优雅 2024-08-02 23:10:43

我从不在我的代码中使用断言,我非常讨厌它们。 我理解错误检查和处理的必要性,但为了防止错误导致您的程序崩溃,从而使您的程序崩溃......坦率地说,我没有看到好处。

另外,在代码中留下一个断言,墨菲定律将确保它最终会使您的程序崩溃。 我更喜欢在处理数据之前检查数据并抛出适当的异常,因此它的处理方式与任何其他异常状态或操作非常相似。 根据我的经验,从用户的角度来看,这产生的软件从长远来看更加稳定,具有确定性的行为。

作为一名软件工程师,当你的程序断言时,你会知道该怎么做,大多数用户只会害怕他们破坏了某些东西,最终不会使用你的软件。 因此,除非您是为工程师开发(这是很有可能的),否则...

从可用性的角度来看,断言是可怕的,即使它们不是“应该”发生的,我们都知道最终它会...


好吧。 .. 从我收到的所有评论和火中我认为我需要进一步解释我的观点,因为它显然不被理解。

我并没有说我没有检查异常、奇怪的值或只是简单的错误状态,我只是说我没有使用断言,因为从最终用户的角度来看,它们以一种可怕的方式关闭系统。 此外,大多数现代语言都提供了另​​一种类型安全的方法来处理这些情况,那么当一个完美的异常可以解决问题时,我会使用断言吗?而且也很好。

在我看到的大多数生产代码中,我注意到主要有两种方法来处理这个问题,在整个代码中涂抹断言,然后在生产中留下大量断言。 这有一种令人恼火的倾向,只是关闭用户的应用程序,我还没有看到一个断言优雅地使系统失败......它只是失败了......繁荣......消失......最终用户只是说“WTF地址 0x330291ff 处出现断言失败错误!!!”

另一种方法,如果你问我的话,甚至是最糟糕的,就是接住扔出的任何东西并将其隐藏在地毯下(见过这些带有空括号的可怕的尝试捕获!!)

这两种方法都无法获得良好的稳定系统。 当然,您可以在测试版代码中使用断言,并在生产代码中将它们全部删除......但是为什么要删除安全网,因为它是生产环境。 我会感到非常惊讶的是,所有这些检查都会削弱您系统的性能。

为自己构建一个良好的异常处理方案,然后……上帝啊……把它留在那里,您将获得更多有意义的系统信息,并且如果始终在上下文中正确完成,而不是因为缺少某些内容而导致某些深层库抛出断言。

在创建库时尤其如此……认为你,库的创建者,可以决定何时关闭整个系统,因为向你抛出的数据出了问题,这是非常自私和狭隘的。 让库的用户决定什么足够重要以至于应该导致紧急故障。

所以不...我不使用断言...我使用异常

是的...通常在生产中失败的代码很少有我的名字在上面。

I NEVER use assertion in my code, I hate them with passion. I understand the need for error checking and handling but to prevent an error that would crash your program by crashing your program yourself .... frankly I do not see the advantage.

Also leave one assertion in your code and murphy's law will ensure that it will, eventually, crash your program. I much prefer checking the data before I do processing with it and throw the appropriate exception so it is handled much like any other exceptional states or operation. This in my experience yielded software that was much more stable in the long run with deterministic behavior from the user's stand point.

You as a software engineer will know what to do when your program asserts out, most users will just get scared they broke something and will end up not using your software. So unless you are developing for engineers (which is quite possible) and even then...

From a usability stand point asserts are horrible, even if they are not "supposed" to happen we all know that eventually it will...


Ok... From all the comment and fire I am getting here I think I need to further explain my point of view because it is clearly not understood.

I did not say I was not checking for exceptions, weird values or just plain wrong states, I just said I did not use assertions because of the horrible way they tent to close the system from a end-user's perspective. Also most modern languages provide another, type-safe way to handle these situations, whey then would I use assert when a perfectly good exception would do the trick, and quite nicely so too.

In most production code I have seen out there I noticed mainly two ways to deal with this, buttering asserts all over the code and then leave a good bunch in production. This has the infuriating tendency to just close the application to the user, I have yet to see an Assert gracefully fail a system.... it just fails it ... boom... gone... end user just saying "WTF is a assertion failed error at address 0x330291ff!!!"

The other way, even worst if you ask me, was to just catch whatever was thrown and hide it under the carpet (ever seen these dreadful try-catch with empty braces !!)

NEITHER WAY will work to get a good stable system. Sure you can use asserts in your beta code and remove them all in your production code... but why the hell would you remove your safety nets because it is production. I would be very surprised that all these checks would cripple your system's performances.

Build yourself a good exception handling scheme and .. by god... LEAVE IT THERE, you will get much more meaningful information our of your system and if done appropriately always in context than having some deep library throwing asserts because something is missing.

This is especially true when creating libraries... to think you, the creator of the library, can decide when to bring down the whole system because something went wrong in the data that was thrown at you is incredibly selfish and narrow minded. Let the user of your library decide what is sufficiently important that it should warrant emergency failure.

so no... I do not use asserts... I use exceptions

And yes... usually the code that fails in production has rarely my name on top.

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