On 2025-04-29 17:29, Matthew Weier O'Phinney wrote:

* Exceptions should not be used for normal application logic flow. If the "error" is recoverable and/or expected, use a different mechanism so you can use standard conditional branching.

As such, there are a lot of situations where I may not want to use exceptions. Two common ones:

* Input validation. In most cases, _invalid input is expected_, and a condition you will handle in your code. Exceptions are a really poor mechanism for this. * "Not found" conditions, such as not finding a matching row in a database or a cache. Again, this is expected, and something you should handle via conditionals.

I don't want to make this into a quarrel, please consider this to be a genuine question -- I'm trying to understand the viewpoint behind the need for such "failed result" channel.

I'm considering this scenario: An update request comes into a controller and passes a superficial validation of field types. The 'troller invokes an action which in turn invokes a service or whatever the chain is. Somewhere along the call stack once all the data is loaded we realize that the request was invalid all along, e.g. the status can't be changed to X because that's not applicable for objects of kind B that have previously been in status Z.

In such situations I have found (according to my experience) the following solution to be a good, robust and maintainable pattern:

Once I find the request was invalid, I throw a ValidationException. No matter how deep in the stack I am. No matter that the callers don't know I might've thrown that. The exception will be caught and handled by some boundary layer (controller, middleware, error handler or whatever), formatted properly and returned to the user in a request-appropriate form.

I currently have no urge to return an indication of invalidity manually and pass it up the call stack layer by layer. Should I want that? In my experience such patterns (requiring each layer to do an `if` for the possible issue and return up the stack instead of continuing the execution) get very clumsy for complex actions. Or have I misunderstood the usecase that you had in mind?

BR,
Juris

Reply via email to