6

First off, I present you the context. I am writing an api in C# and ASP.NET Core and I am trying to follow the clean architecture.

In summary : I don't know where to put my exceptions. I have written a little scenario where I explain my logic.

  1. Suppose that I throw a DuplicatePersonException in a concrete gateway.
  2. This exception will be caught by my use case (interactor) as a simple exception. I don't think that the use case has to know the real exception.
  3. When I catch the error, I will call a method in my OutputBoundary (presenter).
  4. In the end, this presenter will format the answer and prepare an adequate ActionResult based on DuplicatePersonException.

If I respect the « inward dependency », I have to put my DuplicatePersonException in my use case layer. Why not in the domain layer ? Because it does not have to know this kind of exception. What's more, I don't know if I have to create an abstract custom exception and extends it both in the gateway layer and in the presenter layer : it makes me a little bit confused.

In fine, this solution doesn’t sound good to me but I am not able to explain why. It does not feel right to put my exceptions in this layer.

In conclusion, if you have any advice or solution, I will accept them with great pleasure !

Thank you very much for trying to help me !

Jesse
  • 3,243
  • 1
  • 22
  • 29
P. Orlando
  • 93
  • 4
  • I agree with you that domain layer shouldn't know about exceptions in data layer. First thing thag appears to my mind is, you can creat your own abstract exception in domain layer. Then wrap it around the exception in data layer. Or even you are able to avoid defining a single BaseException class and divide it to a few general BasExceptions. – Hassan Alizadeh Jul 20 '21 at 23:49
  • If you found something better please share it with us – Hassan Alizadeh Jul 20 '21 at 23:50
  • Could you share some code? – Matt Oct 12 '21 at 13:18

1 Answers1

0

(I think the image in this classic article illustrates the layers in the question, if "entities" and "domain" is the same thing: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)

First, there is no point in throwing exceptions that the calling code cannot catch. Then you might as well throw Exception instead.

This is the same idea as returning entities. If your entities were defined in your gateway, your use case wouldn't be able to receive them.

Say your gateway fetches a PersonEntity from the database or an external API. In clean architecture, PersonEntity should be defined in your gateway, and mapped to another PersonEntity in the domain, and then mapped to another PersonDto in the presentation.

These entities are completely separate; none of them extend the other. That would defeat the purpose, I think.


Here's my suggestion:

Define and catch DuplicatePersonException in your use case layer.

Define another, more general exception in your domain layer (maybe InvalidDataException), and throw this from your use case (or forward in a method call).

Christian Davén
  • 16,713
  • 12
  • 64
  • 77