As far as I understood in Eiffel, the following code without assertions fails if the statement returns False
check
i_m_alive: i.alive
then
do_nothing
end
Maybe I'm badly using it but sometimes I'd like to check it without doing anything else.
raise
with an if
statement?check ... then
but its not implemented I'm sure for a reason, probably because there is no alternative as an exception is raised in case the statement returns True
Specially on EWF (Eiffel Web Framework) the only way I see to report an error and treat it is either to write into logs or sending the details to the referrer with some details which are sometimes not adequate to send to the user. Sending an email to the administrator is also a possiblity... I'm a bit lost, but know that the raise and Exception mecanisms is not the way Eiffel recommends to treat errors.
I'll dig further into the available documentation about that but think as me the TL;DR will be happy to have a more concise answer or more points of view about that.
Think of assertions as of statements that specify current state of the program in your code. For example:
here the variable x
is equal to 5
;
here all elements of the list are attached to existing objects;
here two structures have the following relationship, etc.
The assertions just describe the behavior of the program (i.e. they are declarative). They do not define the behavior (i.e. they are not imperative).
Assertions could come in different forms: class invariants, pre- and postconditions, loop variants, etc. But all of them are declarations of the program state when execution reaches the corresponding point at run-time. Removing such declarations does not change the behavior. Whether assertions are checked or not is controlled by compiler and run-time options. If the program is correct, i.e. no single assertion is ever violated, such removal does not affect the final result (except, maybe, performance). Moreover, some tools can verify the assertions at compile time, so that run-time checks are not needed at all. In other words, assertions are used to specify program behavior whereas other code is used to implement the behavior.
However, if the program is incorrect, an exception is triggered. It tells the programmer that there is an error and that it should be fixed.
The same applies to the construct check ... then ... end
. It says that the specified conditions are always met (if the implementation is correct). If the condition is violated, there is a bug in the program. That's why there is no else
part: this construct does not control program execution, it just checks that the execution goes as expected.
If the compiler would be smart enough, if could check the condition at compile time and either report an error, or remove the condition altogether (if it is provably never violated). However, the current technology is not still there. As a result, the code to check the condition (let's call it "assumption") is generated and checked at run-time. In particular, it ensures that the code in then
part can safely rely on the checked assumption. Such checks become critical in void-safe code when the compiler cannot correctly infer attachment status of the expression that is known (to you as a developer) as always attached. Unlike other assertions, this one cannot be turned off (in fact, some preconditions cannot be turned off in SCOOP as well - they are part of the semantics).
If you want to use exceptions as a way to control program behavior, assertions is not the right tool. As you mention, explicit calls to raise
exceptions should be used instead.
To summarize:
assertions describe program behavior, they are not intended to affect the behavior;
exceptions that control program behavior should be raised explicitly (and this should be avoided);
check ... then ... end
is mandatory and is checked regardless of compiler and run-time settings;
there is no else
part because assertions do not control program behavior.