Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why not to put exceptions from the data layer into domain layer? #141

Closed
risayew opened this issue Apr 22, 2016 · 6 comments
Closed

Why not to put exceptions from the data layer into domain layer? #141

risayew opened this issue Apr 22, 2016 · 6 comments

Comments

@risayew
Copy link

risayew commented Apr 22, 2016

Why not to put exceptions from the data layer into domain layer and make them as a part of business logic? In that case the presentation layer will be completely separated from the data layer: now the ErrorMessageFactory class uses NetworkConnectionException and UserNotFoundException from the data layer.

@risayew risayew changed the title Why not to put exceptions from the data layer in domain layer? Why not to put exceptions from the data layer into domain layer? Apr 22, 2016
@Trikke
Copy link

Trikke commented Apr 22, 2016

Because those exceptions belong there. An exception like, for example, "CacheKeyMissingException" should reside in the same layer that it is used, ie: data layer. The exception "ButtonTextEmptyException" is obviously related to ui, so it belongs in the presentation layer. Keep exceptions where they belong. Exceptions are not part of any "logic", nor should be used as a control flow. Also, because the way this project is set up, you need one "entry point" to start the app and know about all the code, and in this case, this is the presentation layer.

I suspect your question pops up because "Exception Handling" is more of a cross-cutting concern, as it something that touches all the layers, but is not exclusively part of one layer.

mobile app archetype_2

So each layer has specific tasks related to "Exception Handling".

  • The presentation layer makes sure the end user is properly notified (via a dialog or something) and cleans up any UI and state problems.
  • the business layer cares about the business side of errors. So there we make sure we don't show any sensitive info to the user, maybe roll back the action that caused the error and returning to a correct state of the app.
  • the data layer is all about problems with data. This means shielding the rest of the app of exceptions that your SQL db might throw, all different types of network errors, data objects that are not available, and more.

So, let's imagine an app where i can order a puppy with the press of a button. I press the button, but i'm on a train driving through a tunnel. I'll press the button, Presentation notifies Business of said press. Business logs "Trikke wants a puppy" via Data in a file. Business call Data to make a request to the API and order a puppy. I'm in a tunnel, so the network request fails miserably after a timeout. Data catches this and notifies Business with a general "ApiNotAvailableException". Business notices and removes the log "Trikke wants a puppy". Business notifies Presentation that an unrecoverable error has happened. Presentation shows me a nice messages stating "We couldn't order you a puppy because the app is experiencing network troubles".
And now we've seen a round trip of an action and each layer is doing it's own part in handeling an error in this action.

@risayew
Copy link
Author

risayew commented Apr 22, 2016

@Trikke, In your example the "ApiNotAvailableException" will be converted to "We couldn't order you a puppy because the app is experiencing network troubles" message in the presentation layer? (in that case "ApiNotAvailableException" is a property of data layer, but the presentation layer has to know about that exception). Is it ok in terms of layered architecture?

@Trikke
Copy link

Trikke commented Apr 22, 2016

Please read up on my other comments on another question about layering. It's a bit of a hard concept, because layering in this project's setup != layers in Clean Architecture. Parts of both the data and presentation layer of this project's setup exist on the same layer in Clean Architecture, so there are no dependency issues.
@android10 has set the project up like this due to a number of advantages, and it is both easier to explain the concept of Clean Architecture and enforce the rules. But i could make a repo with only one project module and have everything in the same namespace and still have a correct architecture in accordance to Clean Architecture. It would just be harder to enforce the rules, i would have more of a mental challenge to respect the boundaries.

@risayew
Copy link
Author

risayew commented Apr 22, 2016

@Trikke, could you help me, please, to place the things in the right way in some specific scenario? :-)

  1. Trikke wants to download a puppy
  2. Business calls Data to make a request.
  3. Data makes request and notices, that the Puppy with some Id is already in the database.
    How to provide an exception to the Presentation and which exception. Because on one hand, there is an "PrimaryKeyException" from database framework, which will be thrown if we will try to add the puppy into database. On the other hand we can define our custom "PuppyAlreadyExist" exception in the data, and throw it before we cache the puppy in the database(simply call subscrier.onError if the puppy was already cached).

@Trikke
Copy link

Trikke commented Apr 22, 2016

Like i said, the "Exception Handling" part of the data layer consist of shielding the app from any problems of external sources (SQL, File storage, Network, ...) which all each have their own set of exceptions and/or problems.
This would mean that indeed, you would create a "PuppyAlreadyExistException" which the data layer throws whenever this scenario happens. Which could be "PrimaryKeyException" in an DB scenario, or "AlreadyInMemoryException" if you would happen to use a MemCache. Maybe you could be using both, first MemCache and then DB, so you catch both exceptions as a "PuppyAlreadyExistException" because they are both the same scenario.
So the presentation layer gets the general "PuppyAlreadyExistException", but not some specific "PrimaryKeyException".

@risayew
Copy link
Author

risayew commented Apr 22, 2016

@Trikke, thank you for your help!

@risayew risayew closed this as completed Jun 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants