I'm working on a project with a multi-layered architecture consisting of four main layers: domain, application, infrastructure, and presentation/REST. In the application layer, I have my use cases where I coordinate all the business logic using Input Ports and Output Ports.
When a use case is executed, various errors can occur, originating from the domain layer, infrastructure layer, or even from the use case class itself.
How can I centralize and specialize error handling for these situations?
My question is not related how to present it. I mean, I have a usecasePresenterOutput like this:
public interface CreateReferencePresenterOutputPort<T> {
T success(CreateReferenceResult createReferenceResult);
T presentPersistenceError(CreateReferencePersistenceError createReferencePersistenceError);
T presentReferencedDocumentIdNotExists(
CreateReferenceReferencedDocumentIdNotExistsError createReferenceReferencedDocumentIdNotExists);
T presentInvalidInputError(CreateReferenceInputError createReferenceInputError);
...
}
My question is overall centralized on how to handle infrastructure exceptions. I mean, there (on infrastructure layer) a lot of exceptions types can be raised, IOException, NoSuchAlgortihm, and a long list of any type of exception.
How could I properly handle them into my use-case class?
I want to ensure that:
- Errors are handled appropriately at each layer without leaking implementation details.
- Error handling logic is centralized to avoid duplication and maintainability issues.
- Different types of errors can be handled differently based on the context, such as retrying certain operations, logging specific errors, or presenting user-friendly error messages.
- I'm looking for best practices or design patterns to achieve this in a clean and maintainable way. Should I use exception wrapping and rethrowing, custom error classes, or some other approach? Any guidance or examples would be greatly appreciated.
Thank you!