Java Exception Anti-Patterns
Achieve Efficient Maintainable and Simple Java Exception handling killing those anti-patterns.
The Silencer
This anti-pattern is everywhere. It’s mostly added in the codebase when fixing a compiler error without using Throws. It makes the JVM scream into a pillow. As a rule of thumb, never catch an exception without logging it, wrapping it, or re-throwing it to the upper level.
The Exceptional Else Block
AKA Coding by Exception. This is opinionated. The definition of exception is: “someone or something that is not included in a rule, group, or list or that does not behave in the expected way”.
IMHO It is wrong to consider the case in which the Exception is thrown as a standard flow. The exception should be handled, as the name implies, as an exceptional case, typically an error, which is something unexpected. The definition of “exceptional” is not subjective. In this case, a better approach would be to check if the file exists before trying to read it.
The Wrapped Silencer
When wrapping an Exception in a custom one, it is fundamental not to lose the original exception.
In this case, the original exception is lost and upper layers can’t access the stack trace and messages. When debugging, this can easily become a nightmare. When wrapping, always use the exception constructor with the “cause” parameter:
The Stack Trace Polluter
When handling exceptions, never log and throw.
This will pollute the logging with repetitive and useless stack traces. Log only what is needed, never log the stack trace more than once.
The Useless Wrapper
The Java.Util package defines a series of exceptions e.g. the IllegalArgumentException. It’s a best practice to reuse them instead of defining useless wrappers that don’t add any functionality or context to the existing ones.
The Custom Exception Freak
Having one custom exception for every small exceptional case it’s a bad practice. It’s way better to adopt the “error code” pattern instead.
The SneakyThrower (Silencer 2.0)
This Lombok Annotation is a code smell. It’s a way to avoid handling exceptions, but it’s not a good practice. It should be used with a lot of caution. It’s better to handle exceptions explicitly, because it makes the code more readable and maintainable.
The Generic Exception Thrower
This is a bad practice. It’s always better to throw a specific exception, so the caller can handle it properly. This doesn’t give callers of your method any information about what might have gone wrong. The same applies for catching Exception, Throwable, and Error. It’s important to always catch the most specific exception possible.