Search code examples
validationdomain-driven-designddd-service

Best way to return error description to user


Suppose I need to register user in my system.

Buisness rules are:

  • email shoud be unique (a kind of identity);
  • name shouldn't be blank.

It looks like I need Service for it.

Probably something like that:

public interface RegistrationService {
  bool Register(String email, String name);
}

And it's fine until I have to return failure reason to user. How to deal with it?

I can see few options (but I don't like any of them):

  1. Implement a kind of result object:

    public interface RegistrationService { RegistrationResult Register(String email, String name); } public interface RegistrationService { bool Succes(); Error[] Errors(); User NewUser(); }

It's fine, and even could be useful for example for REST api. But isn't it too cumbersome(especially considering that blank name probably should be checked at factory)?

  1. Throw exceptions

    public interface RegistrationService { void Register(String email, String name) throws RegistrationError; }

It looks a bit more accurate. But exception are expensive. Using them like this is looks like bad idea.

  1. Use DB constraint. But it looks even more messy than (2).

Solution

  • let's start with point 3: DB constraints get their job done. Yes, the exception/error message is messy, I agree about that. But ask yourself: What is more messy: a terrible error message shown to 1 user or 2 user accounts with the same email adress that can corrupt your system? The DB constraint should be your last safety net. Your service needs to check if a user account with this email already exists. But what happens if in another thread somebody creates a user account with this email in the microsecond between your check and the creation of the new user account? You'll be happy about the DB constraint. Yes, you could find a better solution, but that would require you to have a singleton service that serializes all account creation and makes sure that no two threads can create a user account at the same time.

    Point 2: Exceptions are for exceptional situations. The situation that somebody wants to create a user account with an already used email is an exceptional situation. Don't be worried about costly operations in situations where somebody wants to do something dirty.

    Point 1: I don't like this. But that's just my opinion. There are situations where a Result Object of this kind makes sense, but I try to Keep it to a Minimum.