I can't find any substantial example of error handling in Eiffel. I have only found examples that either are trivial, or they completely ignore errors, or they leave error handling to the reader. I am interested in knowing how errors can travel through the call stack in absence of exceptions. For example, I would like to know how an application that sends a network request would inform the user of a network problem that has been detected down the call chain. Something like that.
--
EDIT: I do know the basics of error handling in Eiffel (statuses and exceptions). However, I can't find any substantial example on how applications handle errors via statuses. How are failure statuses chained?
Eiffel advocates use of an object state instead of exceptions. In that case clients may figure out what they expect in case of an error and handle it properly. For example,
The client can then reason about the state of the supplier object and continue using it in a predictable way:
In presence of exceptions one cannot deduce what should be done in what case except from some documentation. Also, it prevents from using automatic tools that can easily check that the use of
response
is perfectly valid in the code above.If an error happens deep down the stack, an exception mechanism can be used with
rescue
/retry
. However it may introduce close coupling between low-level network component and user interface that has nothing to do with details of network failure. In the simplest case, the network class will call{EXCEPTIONS}.raise
with an appropriate message. A more specific approach would be to create an object of typeEXCEPTION
(or a descendant), to set the corresponding message by callingset_description
on it, and to raise an exception by callingraise
. The user code that will handle the exception may look like.EDIT
A specific way to handle nested errors depends on the application design and seems to be irrelevant to the language. Possible alternatives are:
(If exception mechanism is used, not recommended.) After catching a (lower-level) exception and handling it to restore the class invariant, a new exception is raised without cancelling the previous one. Then a query
{EXCEPTION}.cause
can be (recursively) used to access nested exception objects.A mechanism similar to the previous one can be used. However instead of creating new objects, a class can delegate a request for details to a lower-level class. For example,
Logging facilities can be used. They can differentiate error severity, specify sources, etc.