This is how we implemented error handling in Java. We defined an
abstract class ErrorSink like in:
class ErrorSink {
void addError(String s);
boolean hasError(s);
// few more methods to add extra attributes like line, file,
column etc of errors
}
A default implementation of the class just throws in the addError
method, but the requirement for addError callers is to assume that
method would not throw and try to recover or return some sensible
value. For example, a method like readFileAsString in case of
IOException reported that and returned an empty string.
A configuration parser that calls readFileAsString to read included
files has a custom implementation of ErrorSink that does not throw but
rather adds all errors on the list. At the end of parsing all those
errors plus all syntax violations was converted into a new detailed
report with proper line numbers etc and reported to the original sink.
This has number of benefits. All unexpected errors like dns failure
when reading URL are nicely formated showing the error origin. Various
low-level helpers like a date parser do not need to worry about
including proper context in the error message as that was
responsibility of the caller. This allowed to reuse the same parser in
GUI dialogs for a date input showing short and very informative
tooltip when user typed invalid date. It was trivial to add warnings
to the system extending the ErrorSink with an addWarning method and
turn those warnings into hard errors at runtime during testing via
simple throw. The callers would not need to check for errors at the
every method call.
The biggest drawback was the need to pass ErrorSink to a lot of
methods or store that as a member of many classes. We experimented
with using Java's thread locals instead, but that was rather
inflexible and inefficient.
I wonder why such error reporting is not used in other programs or languages.
On 18 October 2013 23:20, Florian Weimer <[email protected]> wrote:
> * Igor Bukanov:
>
>> So the Go style is to call a function, check if the was an error,
>> update the error object (or create a new wrapping the old one) with
>> extra information relevant to the current call stack frame and
>> propagate the updated error object to the caller.
>
> It's more common to simply return the object.
>
> Due to some obscure feature of Go's type system, error values have to
> be interfaces and cannot be struct types, so I have not seen anyone
> trying to updating an existing error. Wrapping might happen, but
> there is no general chaining mechanism like there is in Java.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev