I've gotten into arguments with other developers on more than one occasion about the value of program assertions.
(By the way, I'm talking about the use of "assert" macros/functions/pragmas in the Ada, C++, and Java programming languages. These languages pay my salary, so while I know about Haskell, Erlang, Eiffel, OCaml, Ruby, etc. I have no call to use any of them. So...YMMV on some of the details.)
Let me try to summarize the anti-assertion position of the last heated discussion I had about this, which was with a very talented C++ programmer:
- Assertions are almost always compiled out of the released code, so they're USELESS!
- If you're asserting something because you think it might break, there should be an explicit check for it in the code, so assertions are USELESS!
You need to step back from thinking of program assertions as just code.
The purpose of effective program assertion practice is embedding encoded information about requirements, design, and implementation assumptions into the code, as code.
Assertions are not to be used to error-check code execution, they're meant to be used to help verify that the software is implemented in accordance with its requirements.
What is being asserted in the following code?
assert(hnd != NULL);
That a pointer is not null, right?
I'm asserting a part of the design specification, the part that specifies that my function will only ever be called with a valid handle. I encode it as a null pointer check, but the purpose is not to check the pointer, it's to verify my code (and my caller's code) as its pertains to the design spec.
Conscientiously crafting meaningful assertions embeds a portion of my understanding of the functionality of that code...in the code.
The assertions themselves can then be reviewed by inspectors or peer reviewers, or the system engineers or architects or whatever. This gives them a means to verify that I have a correct understanding of what this piece of code is supposed to do. The assertions encode requirements and design aspects in the medium of code, and those notations of my understanding can be checked for accuracy. Do the asserted ranges for guaranteed inputs match the spec? Do my assertions reveal that I'm not allowing for the full range of allowable inputs? Are constraints being asserted that I should in fact be explicitly checking?
Embedding design-oriented assertions into the code aids the inspectors or peer reviewers in verifying that the implementation matches the design.
Embedding implementation assumptions as assertions helps inspectors verify that the code corresponds to the requirements, design, and the implementation assumptions.
Assertions are intended to capture the developer's understanding of what a given piece of code is supposed to do--they're not a coding thing, they're a correctness thing.