Search code examples
domain-driven-designonion-architecture

Exceptions from Infrastructure to Presentation layers in DDD


I have a desktop app using Onion Architecture where the user should be able to create and edit local files on disk. I have the following layers:
Presentation->Application->Domain
Infrastructure->

I want to be able to present issues when working with files to the user so the user can take some action like choosing whether to overwrite a file if it already exists. But as I understand DDD the application layer should have no knowledge of the persistence specifics in the Infrastructure layer. My thought was that an exception (e.g. FileExistsException) could be a part of the Interface contract in the Application layer and thrown from the implementation in the Infrastructure layer but then the Application layer would know about the storage type.

Is this perhaps ok since working with files is a part of the Application scope?

My questions is mainly regarding exception handling but I see that there could be other information to be shared as well.

Update:

To expand the question a bit and be more specific the user works with data models that is saved as a JSON file so I have those data models in the domain and the concept of File is only used in the infrastructure layer when actually persisting/changing the file.

If, in the future, I would like to give the user an option to change the storage from local disk to a database where they would get completely different types of exceptions to handle, would the necessary database specific info also be added to the domain?

In other words can implementation details be added to the domain if it is necessary for the user to interact with even though it is not necessarily a part of the actual business?

In my mind the way the user stores information is implementation detail and should stay out of the domain?


Solution

  • Since File is a concept in your Domain the FileExistsException should be inside your domain. But the actual persistence mechanism should be in your infrastructure layer.

    You can achieve that using repository: in the Domain layer you can define a FileRepository which is an interface with some method and in the infrastructure you define the actual implementation for example LocalDriveFileRepository.

    Update:

    How you persist your data is important only in the infrastructure layer so your application layer cannot handle an exception of type FileExistsException because it should not have knowledge of something outside domain and application layers.

    You should remap your infrastructure exception into domain exception.

    For example a FileExistsException could be remapped to a UserAlreadyPresentException or some other exception that have some meaning in your domain.