Is assert evil?

31,561

Solution 1

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.

Solution 2

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.

Solution 3

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".

Solution 4

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.

Solution 5

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.

Share:
31,561

Related videos on Youtube

Frank
Author by

Frank

Updated on July 08, 2022

Comments

  • Frank
    Frank almost 2 years

    The Go language creators write:

    Go doesn't provide assertions. They are undeniably convenient, but our experience has been that programmers use them as a crutch to avoid thinking about proper error handling and reporting. Proper error handling means that servers continue operation after non-fatal errors instead of crashing. Proper error reporting means that errors are direct and to the point, saving the programmer from interpreting a large crash trace. Precise errors are particularly important when the programmer seeing the errors is not familiar with the code.

    What is your opinion about this?

    • allyourcode
      allyourcode over 8 years
      tangent: Go is an unusually opinionated language. This isn't necessarily a bad thing. However, it does mean you should take its opinions with a bigger grain of salt. It also means that if you disagree, you are going to be gnashing your teeth as you use the language. As evidence of how Go clings to its opinions despite reality, consider that you need to resort to the magic of reflection to determine if two collections are equal.
    • Igor Dubinskiy
      Igor Dubinskiy over 8 years
      @allyourcode If you're referring to reflect.DeepEqual, you certainly don't need it. It's convenient, but at the cost of performance (unit tests are a good use case). Otherwise, you can implement whatever equality check is appropriate for your "collection" without too much trouble.
    • allyourcode
      allyourcode over 8 years
      No, that's not what I'm talking about. There is no such thing as slice1 == slice2 without reflection. All other languages have an equivalent to this super basic operation. The only reason Go does not is prejudice.
    • kbolino
      kbolino over 6 years
      You can compare two slices without reflection using a for loop in Go (just like C). It would be really nice to have generic slice operations, although comparison gets complicated when pointers and structs are involved.
  • Peter Cordes
    Peter Cordes over 14 years
    assert is good for declaring the pre-conditions at the top of a function, and if clearly written, acts as part of the documentation of the function.
  • Admin
    Admin over 14 years
    If you look at my answer. My use is to differentiate 'exceptions' (asserts) that i want to get rid of used for debugging vs exceptions that i keep. Why would i want to get rid of them? because without them working it would not be complete. Example is if i handle 3 cases and the 4th is todo. I can easily search assert to find them in code and know its incomplete rather then use an exception that might accidentally be caught (by another programmer) or hard to tell if i its an exception or a logic check that i should solve in code.
  • Evan Carroll
    Evan Carroll over 14 years
    In my eyes, this is a poor idea, on the same level as "sealed" classes and for just the same reason. You're assuming the exceptions you want to keep are acceptable for uses of your code you don't yet know of. All exceptions go through the same channels, and if the user doesn't want to catch them he can choose not to. If he does, he should have the ability too. Either way, you're just making assumptions or pushing off your practice with a concept like an assertion.
  • Admin
    Admin over 14 years
    I decided example scenarios are best. Heres a simple one. int func(int i) { if(i>=0) { console.write("The number is positive {0}", i); } else { assert(false);//to lazy to do negatives ATM } return i*2; <-- How would i do this without asserts and is an exception really better? and remember, this code will be implemented before release.
  • Evan Carroll
    Evan Carroll over 14 years
    Sure exceptions are better, lets say I take user input and call func() with a negative number. Now, suddenly with your assertions you've pulled the carpet out from under me and not given me a chance to recover, rather than politely telling me what I'm requesting can't be done. There is nothing wrong with accusing the program of being misbehaved and issuing it a citation: the problem is you're blurring the act of enforcing a law, and sentencing the felon.
  • Admin
    Admin over 14 years
    Thats the point, you SHOULDNT say what the user wants to do cant be done. The app should terminate with the error msg and whomever is debugging would remember its something that SHOULD BE DONE but isnt. You DONT want it to be handled. You want a termination and to be reminded you didnt handle that case. and its extremely easy to see what cases are left since all you need to do is a search for assert in code. Handling the error would be wrong since the code should be able to do it once ready for production. Allowing a programmer to catch it and do something else is wrong.
  • Admin
    Admin over 14 years
    NOTE to others. The func in my example above should do console.write("The number is negative {0}", i); and not throw an exception. This is why assert is a DEBUG tool and not an error handling tool. Thats why no one should write draw(){ Assert(image.exist()) because saying it isnt handle or the user did it wrong (exceptions) isnt the same as saying it will be handled but isnt yet.
  • Evan Carroll
    Evan Carroll over 14 years
    re You DONT want it to be handled.. You shouldn't code assuming you know the use-cases of your code. It doesn't matter what you want, if someone else wants to handle it they should be allowed to, it is their freedom to do what they wan't and you shouldn't impose yourself with code. You disagree, you want to be the controller of your codes application. That is fine, I just disagree that it is ever a good thing. Your examples say something of your argument, if you try to draw an image that doesn't exist, the whole program should die because it failed your assertion... right...
  • Admin
    Admin over 14 years
    No you misunderstand. I am not saying you shouldnt be able to handle it the way you like. I am saying if the function should be able do something like load an image and it doesnt then an assert should be in place because your not done the code yet and if you accidentally load an image forgetting your not done it you'll notice it instead of running into exception code. This is why the draw code should never check if an image exist with an assert. An assert belongs in an empty loadimage function and an exception belongs in a draw function when no image has been loaded.
  • vmasule
    vmasule over 13 years
    The difference is "exceptional" vs. "impossible". See here: stackoverflow.com/questions/1467568/…
  • João Portela
    João Portela over 13 years
    90% percent of statistics used in arguments are false.
  • Zippo
    Zippo over 12 years
    Not too bad :-) Exceptions or not, assertions or not, Go fans are still talking about how short are the codes.
  • David Stone
    David Stone about 12 years
    new never returns nullptr, it throws.
  • Nir Friedman
    Nir Friedman about 9 years
    Go does not have exceptions. The usual reason to use an assert rather than an exception is because you want it elided in deployment for performance reasons. Asserts are not archaic. I'm sorry to sound harsh, but this answer is not remotely helpful to the original question, nor correct.
  • markand
    markand over 8 years
    Note that you can use std::nothrow for that.
  • ar2015
    ar2015 about 8 years
    how to use goto wisely?
  • underscore_d
    underscore_d about 8 years
    @ar2015 Find one of the absurdly contrived patterns that some people recommend to avoid goto for purely religious reasons, then just use goto rather than obfuscating what you're doing. In other words: if you can prove you really need goto, and the only alternative is to enact a load of pointless scaffolding that ultimately does the same thing but without alterting the Goto Police... then just use goto. Of course, a precondition of this is the bit "if you can prove you really need goto". Often, people don't. That still doesn't mean it's inherently a Bad Thing.
  • malat
    malat about 8 years
    goto is used in linux kernel for code cleanup
  • Gaspa79
    Gaspa79 over 3 years
    The only place so far I found goto to be absolutely superior is to create an abort-retry-ignore logic with user confirmation. It makes the code much easier to read and write in that case (this is just an opinion). The other not-so-superior case is to break outside switch statements to another switch statement in languages like C# that do not allow fallthrough.