Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is assert evil? [closed]

No, there's nothing wrong with assert as long as you use it as intended.

That is, it's supposed to be for catching cases that "can't happen", during debugging, as opposed to normal error handling.

  • Assert: A failure in the program's logic itself.
  • Error Handling: An erroneous input or system state not due to a bug in the program.

No, neither goto nor assert are evil. But both can be misused.

Assert is for sanity checks. Things that should kill the program if they are not correct. Not for validation or as a replacement for error handling.


By that logic, breakpoints are evil too.

Asserts should be used as a debugging aid, and nothing else. "Evil" is when you try using them instead of error handling.

Asserts are there to help you, the programmer, detect and fix problems that must not exist and verify that your assumptions stay true.

They have nothing to do with error handling, but unfortunately, some programmers abuse them as such, and then declare them "evil".


I like to use assert a lot. I find it very useful when I am building applications for the first time (perhaps for a new domain). Instead of doing very fancy error checking (that I would consider premature optimization) I code fast and I add a lot of asserts. After I know more about how things work I do a rewrite and remove some of the asserts and change them for better error handling.

Because of asserts I spend a lot of less time coding/debugging programs.

I've also noticed that the asserts help me think of many things that could break my programs.


As an additional information, go provides a built-in function panic. This can be used in place of assert. E.g.

if x < 0 {
    panic("x is less than 0");
}

panic will print the stack trace, so in some way it has the purpose of assert.


They should be used for detecting bugs in the program. Not bad user input.

If used correctly, they are not evil.


This comes up a lot, and I think one problem that makes defenses of assertions confusing is that they are often based on argument checking. So consider this different example of when you might use an assertion:

build-sorted-list-from-user-input(input)

    throw-exception-if-bad-input(input)

    ...

    //build list using algorithm that you expect to give a sorted list

    ...

    assert(is-sorted(list))

end

You use an exception for the input because you expect you'll get bad input sometimes. You assert that the list is sorted to help you find a bug in your algorithm, which by definition you don't expect. The assertion is in the debug build only, so even though the check is expensive, you don't mind doing it on every single invocation of the routine.

You still have to unit-test your production code, but that's a different, and complementary, way of making sure your code is correct. Unit tests make sure your routine lives up to its interface, while assertions are a finer-grained way to make sure your implementation is doing exactly what you expect it to.