Exceptions are a communication channel, not noise to suppress. The goal is to fail loudly at the right layer with enough context to diagnose the problem.
Catch narrowly, wrap with context
Catching Exception hides bugs you never intended to handle. Catch what you can
recover from and wrap the rest with a message that explains what you were doing.
try {
parser.parse(file);
} catch (MalformedInputException e) {
throw new ImportException("Invalid encoding in " + file.getName(), e);
}Never swallow silently
An empty catch block is where bugs go to hide. If there is truly nothing to do, document why in a comment.
try {
risky();
} catch (IOException e) {
// never do this
}Takeaways
- Prefer unchecked exceptions for programming errors, checked for recoverable ones.
- Always preserve the original cause when rethrowing.
- Log at the boundary where you handle, not everywhere you catch.
Create a small set of domain exceptions rather than throwing raw
RuntimeException, so callers can react meaningfully.