Search code examples
typescriptdomain-driven-design

Return vs Exception


I'm doing an application in Typescript using DDD and hexagonal architecture and I'd like to know in which cases I should return false in validations and in which other ones I should throw an exception.

As far as I have understood, an exception is thrown when you don't have that error handled, you don't expect that thing to happen, but then I see better programmers code using DDD as well and they are using Not Found exceptions, which obviously you should have that handled.

In my example, I want to do a validation in a valueObject that looks like this:

public static nameValidation(name: string): boolean {
    if (Name.containsSpecialChars(name)) {
      return false;
    }
    if (name.length < 2) {
      return false;
    }
    return true;
}

I have put this as a boolean that return false in case that the validation is not okay, but could easily change this into an exception.

I don't really know how to distinguish which has to go where.

Any thoughts?


Solution

  • Your instinct is correct, this is a true / false response (generally - imo).

    Validation is checking the input is correct, and you should think about it as - not "exceptional" - as in, you expect users to do silly things.

    I see lots of examples of developers using Exceptions as a way of capturing basic errors - mostly this just wrong (especially in DDD) [though not a hard and fast rule].

    In most cases you should consider anything failing "business logic" as simple an error response. Whereas Exceptions should be reserved for something going exceptionally wrong.

    Examples of exceptions...

    • Cannot find & connect to database
    • Database query timed out
    • Timed out response from 3rd party API.

    A boolean response on some validation is really a business logic concern, and should respond appropriately.

    Extra Info

    You will find times, when you throw an exception, because the bad input shouldn't have made it that far - aka - you expected the implementing developer to handle that issue at their level.

    Steps...

    1. Check for error condition (implementor)
    2. Handle incorrect condition (implementor)
    3. Throw exception, because it shouldn't have got this far - not all conditions were handled. (final library).

    Just a quick explanation; happy to expand.