views:

693

answers:

14

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? Btw, I'm using unit tests.

cheers jan

+2  A: 

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.

geowa4
+7  A: 

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.

Nosredna
"use assertions for conditions that should never occur." I always though that sounded a lot like exception handling.
geowa4
exception handling is for things you know why they occur and that you can deal with inside the program. If an assertion fails something is so wrong you don't know what to do and the program should quit.
Janusz
@George IV: The difference is that assertions are for things which you believe that, if your program is correct, are impossible. Exceptions are for things that "shouldn't" happen in the sense that your routine/program cannot work if they do. Hence libraries sometimes throw exceptions for things where an application would assert, since the library doesn't know whether or not the problem is inconceivable from the POV of the program (e.g. out of memory: in some environments you can code to avoid it, in others you can't).
Steve Jessop
+14  A: 

Andrew Koenig has 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.

cdleary
Great link, never really seen the point of asserts till reading it.
MitMaro
+2  A: 

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.

Larry Watanabe
assertions slow down code. We used them in videogames and they were there during much of testing. They had to be stripped out after. You don't assert on a GameCube.
Nosredna
A: 

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.

Janusz
A: 

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.

Newtopian
they are exactly for this moment. the moment murphys law takes your program and you don't know what it is doing afterwards. If you don't like them you can take them out and add an error handling at the position but if you error handling does something other than display unexpected error ... occured please contact support guy it isn't a place for an assertion and the error handling is correct at this place.
Janusz
If you use assertions, then at least you know where your program failed and what internal inconsistency caused it to fail. If you choose to ignore conditions that would cause an assertion to fail, then your program could crash at any later time, or even give wrong results without complaint. Neither of those cases is better for the user, but they are both worse for the programmer trying to debug (and everybody in the tech support chain between the user and the debugger).
Yeah, someday they'll fire in production code. That's a *GOOD* thing assuming your program provides some means of doing an emergency save (assuming it has some sort of document in the first place.) When you hit an impossible situation you should *NOT* attempt to continue. Save, *NOT OVERWRITING*, and exit.
Loren Pechtel
@Janusz - Personally I think the popup "an error has occurred" or an assert are pretty much equivalent, that is, next to useless if your software stack becomes very large and just degrade really badly the end-user experience.
Newtopian
@unknown... I can do the same with exception, I see not where an assertion can do more than the exception already can. It the user of my library decides that this exceptional situation is not bad enough and decides to continue nonetheless then the error is his, not mine. Also... he may very well be right, to you, the library creator, it may be an irrecoverable error, but to him, he may have a contingency plan that he can use. Asserts would not give him this flexibility.
Newtopian
@Loren - wow... so you always have the overview over the whole software stack and can always decide when it should crash down !!?? now there is someone I would not want in my team. If you rely on lower libraries to crash the stack when they do not have proper states then I suggest you expand your horizons and start learning to deal with exceptional situations. It will be hard at first... all this extra code but trust me... your support guy will love you for it, and in 20 years from now may prevent YOU from getting fired.
Newtopian
+5  A: 

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.

David Norman
+2  A: 

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.

Brian Neal
+2  A: 

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.

psquare
A: 

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.

Pete Kirkham
A: 

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.

Steve Jessop
A: 

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.

Nemanja Trifunovic
A: 

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

Denis
+2  A: 

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.

jalf
I think that many posts here are true, but this one is really close to my phylosophy. Asserts help me while developing, while constructing my application. I prefere it to stop and generate a crash dump once an error occured that I do not expect while doing my development .. race :-) . +1 !
yves Baumes
That's probably what does formula one team when developping new engine (for instance). They put their engine at test on a circuit with many sensor and other stuffs. When people in the pit detects errors, they ask the driver to stop at the pit to do some correction, etc, etc, etc. Up the time they reach their goal: an engine that is ready for .. production. :-)
yves Baumes