A couple of pages (WhatAreAssertions
) have blithely proclaimed the wisdom of turning assertions off in a shipping product. I contest that wisdom.
I'll speak in the context of assertions written for C code, and presume the same things are relevant in other languages.
Your program will crash.
Even if our code won't crash, someone else's code will.
(Pretty plausible as axioms go!)
Since your program is going to crash, you should make some effort to do something about it. This is core to IBM's AutonomicComputing
(or whatever it's called), without all the hoo-hah.
Since your program is going to crash, and you're going to the effort to do something about it, then it makes perfect sense to ship with assertions enabled. Your program might crash a little more often, but that's OK, you can deal with it. More importantly, DeadCodeTellsNoTales
; turning off assertions means the program gets further, and has further opportunity to further corrupt the surrounding system, than if the assertions had been left on. If you know your plane is going to crash, you're better off jumping out a thousand feet off the ground than waiting until the wings are clipping the treetops. (Assuming you thought to bring a parachute!)
As a real-life example: I was working on a project that involved a network server program. We deliberately left the assertions on in this program. Since we had written the server with the cheesy fork-process-for-new-connection approach, a crashed server could be dealt with by having the client automatically reconnect (which it did anyhow).
That same project involved boards on the server with their own software. They had an assertion-like mechanism that essentially said "I've fallen and I can't get up." When the server machine received this notification, it cold-restarted the board.
I HaveThisPattern. It is best used in conjunction with FailFast, ReportBugsSilently, and KeepErrorInformation (which are not just testing patterns). Also very compatible with the ErlangLanguage approach of "let some other process do the error recovery". -- DavidSarahHopwood
There is a hidden legal liability. Shipping debug code leaves the company's intellectual property open to easier reverse engineering, thereby diluting the company's value, and not maximizing shareholder value
! If you're going to turn assertions on, write your own release mode assertions. As an extra added benefit, you get to test the software in the much more strict release mode without all those fun debug lies like all pointers are initialized to 0. -- anon
Piffle - producing a reliable product is far more important. Let your competitors waste their time trying to make head or tail of reverse-engineered code. The only question is, how to convince the PointyHairedBosses of that?
- Producing a reliable product is about 1/100th as important as protecting your company's intellectual property and hampering competition. You can delude yourself that you were hired to make good software. You were hired to make your company money. A good quality product that is easy to steal is nearly worthless. Bad quality music sold in the 80s far better than high quality music today because of IP theft.
[See also "no source is a
feature" at SeriousVersusScriptingLanguages
Assertions are different from all other debug code. They end the program if there was a bug. That's it. If you use a good library, you can make assertions not show the filename and the line of code, thus having the program quit gracefully on error and not expose details about the source of the program. In addition, what is wrong with extra debug bonuses? we try to make coding harder? if initializing pointers to 0 doesn't hurt you, why not keep it? -- AmirLivne
If you are doing necessary checks for the shipped code, do not use assertions, use explicit checks. If you are implementing debug aids for developers using your class then use assertions. When a C programmer sees "assert()," he will assume it is not a run-time check and ignore it. I do not believe the world will come around to this personal point of view, so it is best to avoid "assert()" for shipped tests; at sometime the code will get built without the assertions turned on. Code explicit verifications where needed. -- anon
What you say seems like "assert() is not popular as a name for runtime checks, so let's not use it". So create a new macro, called RTCheck(), and add sanity tests there. this will be explicit enough, and won't be undefined when you switch from debug mode to release mode. -- AmirLivne
Actually, in C, "assert()" is a well defined macro with embedded switches to turn it off if "DEBUG" is not defined. As the poster above noted, it is quite easy to create a new name that has not been previously defined and all of the issues about enabling "assert()" go away.
I think that one benefit of assert() is as a psychological aid to combat PrematureOptimization
. Too often I (and I assume other programmers) think "Hey, I bet this routine would run faster if I left out all those run-time checks. I'm pretty sure the calling code already makes sure this number is in a valid range ...". The assert() macro tells us programmers "No, these run-time checks do *not* make the (released) code any slower. Leave them in. They are "merely" a superior kind of comment (ReplaceCommentWithAssertion
).". When the code seems to be running slowly, this helps me focus on getting it to work *correctly* first (rather than get sidetracked with PrematureOptimization
), with the UsefulLie
that "hey, once I get it working correctly, I can always recompile in ReleaseMode?
(assertions turned off) and it will really fly".
Much, much later, *after* I've released the first version that works correctly, I *then* recompile in ReleaseMode?
and expect it to really zoom along. I get the impression lots of other people do the same thing; that's why so much software says "Please don't complain about the speed. This is a beta version for testing functionality. We know it is slow. The release version will be much faster."
is also useful when someone says "I want to see the assembly-language code for that subroutine". That sort of person seems to be much happier to see the version with assertions turned off.
But because "if it's not worth measuring to prove it's more efficient, then it's not worth sacrificing clarity for a performance gamble." (SteveMcConnell
1993 ... I think MichaelAbrash
says something similar), I always *measure* how much faster the ReleaseMode?
version of the program is from the DebugMode?
I'm sure there's some psychological explanation for the fact that just about every time, I'm shocked and surprised that the ReleaseMode?
isn't measurably faster.
This measurement tells me I might as well ShipWithAssertionsOn
I view assertions in C/C++ code as being unit tests embedded in the application. Based on that, I would consider moving the assertion out of the application code and into a unit test code base. If you want presentable user error messages, code those in directly without relying on assertions. Common practice is to ship with assertions turned off and whatever is decided today may be very likely changed in the future, so if you want the error handling preserved, put it explicitly in the code so that there is no confusion over the intent. -- WayneMack
There are different levels of assertions. An assertion may be a simple integer or even string compares. Or an assertion may be an exhaustive verification of a large data structure that is executed each time though the loop. The latter kind need to be turned off. Even in our most performance sensitive code integer compares have been found to be ok.
Stuart Celarier ( http://cs.ferncrk.com/blogs/stuart/archive/2006/01/22/subversion_stunning_revelations.aspx
) claims that Subversion "made a deliberate conscious decision to always compile asserts into the release code (i.e., never define NDEBUG).", and comments that "this is the released version of Subversion, so why are asserts being compile in?! This is utter madness."
I use a simple metric for assertions, assertions are things that "can't happen", because I "know" that is was checked a few layers out. Technically there should be no code path that leads to the assertion to fail. The primary goal of assertions are to prevent new developers or myself to break the code latter.
See also: ExposeErrors