Validation 将错误描述返回给用户的最佳方法

Validation 将错误描述返回给用户的最佳方法,validation,domain-driven-design,ddd-service,Validation,Domain Driven Design,Ddd Service,假设我需要在我的系统中注册用户 商业规则包括: 电子邮件应该是唯一的(一种身份) 名字不应该是空的 看来我需要服务 可能是这样的: public interface RegistrationService { bool Register(String email, String name); } 在我必须向用户返回失败原因之前,一切都很好。 如何处理 我可以看到几个选项(但我不喜欢其中任何一个): 实现一种结果对象: 公共接口注册服务{ 注册结果寄存器(字符串电子邮件、字符串名称);

假设我需要在我的系统中注册用户

商业规则包括:

  • 电子邮件应该是唯一的(一种身份)
  • 名字不应该是空的
看来我需要服务

可能是这样的:

public interface RegistrationService {
  bool Register(String email, String name);
}
在我必须向用户返回失败原因之前,一切都很好。 如何处理

我可以看到几个选项(但我不喜欢其中任何一个):

  • 实现一种结果对象:

    公共接口注册服务{ 注册结果寄存器(字符串电子邮件、字符串名称); } 公共接口注册服务{ 布尔成功(); 错误[]错误(); 用户NewUser(); }

  • 这很好,甚至可以用于RESTAPI。 但这不是太麻烦了吗(特别是考虑到空白名称可能应该在工厂检查)

  • 抛出异常

    公共接口注册服务{ 无效注册表(字符串电子邮件、字符串名称)抛出RegistrationError; }

  • 它看起来更准确一点。但例外情况是昂贵的。像这样使用它们看起来是个坏主意

  • 使用DB约束。但它看起来比(2)更混乱

  • 让我们从第3点开始:DB约束完成它们的工作。是的,异常/错误信息很混乱,我同意这一点。但是问问你自己:还有什么更糟糕的:一条可怕的错误消息显示给1个或2个用户帐户,它们的电子邮件地址相同,可能会损坏你的系统?DB约束应该是您最后的安全网。您的服务需要检查此电子邮件的用户帐户是否已存在。但是,如果在另一个线程中,在您的检查和创建新用户帐户之间的微秒内,有人使用此电子邮件创建了一个用户帐户,会发生什么情况?您将对DB约束感到满意。 是的,您可以找到一个更好的解决方案,但这需要您有一个单例服务,该服务序列化所有帐户创建,并确保没有两个线程可以同时创建用户帐户

    第2点:例外情况适用于例外情况。有人想用已经使用过的电子邮件创建一个用户帐户的情况是一种例外情况。在有人想做一些肮脏的事情的情况下,不要担心代价高昂的操作


    第一点:我不喜欢这样。但这只是我的意见。在某些情况下,这种类型的结果对象是有意义的,但我尽量将其保持在最小值。

    不同的层可以有不同的方式来考虑问题并发出信号。仅仅因为基础设施引发异常并不意味着其他层都应该这样做

    你可以:

    • Infrastructure:引发重复密钥异常,因为客户端不会威胁数据库的完整性
    • 应用程序:捕获异常并返回一个简单的
      RegistrationResult.Failure
      值,因为这是一个预期的失败案例
    • 演示文稿:返回HTTP 409冲突

    错误描述是一个应用程序/UI问题,不必对域进行任何处理。在您的域中抛出异常,在应用程序层捕获它们,并将其转换为可供应用程序使用的内容user@Tseng你是说第二种变体吗?是的。例外并不昂贵,除非你必须抓住它们。如果是webservice/restapi,那么您应该已经进行了一些输入验证(当然不涉及业务逻辑),并且在输入验证错误时甚至不调用域。异常存在于输入验证过程中,或者无法在输入验证过程中完成(因为需要业务逻辑或数据库输入)的情况下。我的意思是,在应用程序/接口层捕获约束异常会造成混乱。至少对于所描述的目标。