Exception Handling¶
Don't be afraid of throwing Exceptions or leaving them uncaught¶
Code just cannot cover every possible kind of Exception, that's why they're called exceptions. Your code should react on exceptions you know that could occur, but be able to deal with exceptions that remain uncaught. Your application should have a global exception handler for these cases (which would be, for example, serving an HTTP error page with a Status Code 500).
try {
try {
url = new Url(aUrl);
} catch (SchemeMissingException e) {
url = new Url("https://"+aUrl);
}
} catch (MalformedUrlException e) {
throw new ValidationException("The given URL was invalid");
}
// if `new Url` still throws an exception we didn't expect here
// the global exception handler would fetch that.
Status Flags¶
Exception handling via status flags should be avoided.
Stacktrace Output¶
Exceptions being logged should contain information that allows diagnostics afterwards. This could be the stack trace for example.
Context-specific Exceptions¶
Context, product, library specific exceptions should not leak out of their component (e.g. "Error connecting to the database"). Instead they should be caught and rethrown or wrapped in a new exception, maintaining the context.
try {
new HttpConnection();
} catch (HttpTransportException e) {
throw new ServiceException("Upstream service could not be called", e);
}
See also the Law of Demeter.
Custom Exceptions¶
Custom Exceptions must be handled consistently across the application.