在应用层验证域对象属性。可以吗?

Validating domain object properties in the Application layer. Is it okay?

DDD中,Application层应该只是执行协调任务,而Domain层负责验证业务规则。

我的问题是关于验证域对象属性。例如,在通过存储库将其持久化到数据库之前,我需要验证所需的 属性 是否具有某些价值。

DDD 而言,在 Application 层执行这种 属性 验证是否可以接受?

您可以在 ui 层中验证传入数据。 例如,您可以使用 symfony 表单验证或仅使用 Rest 检查层内的必要数据。

领域层呢,看情况。
您没有确切说明它是哪种域对象。

大多数情况下,您通过创建值对象来执行此类验证,其中包含创建逻辑。例如Email Value Object,不能创建错误,否则会抛出异常。

聚合可以在执行方法之前执行验证,这称为不变量。例如,用户有方法becomeVIP,方法内部有约束,只有名称为'Andrew'的用户才能成为VIP。 因此,您不会在操作之后进行验证,而是在操作之前进行验证。不要让聚合进入错误状态。

如果您有与聚合无关的逻辑,您可以将其放在域服务中,例如电子邮件唯一性检查。

验证类型

在您描述的情况下,您需要分别考虑两个不同的验证步骤

  • 输入验证。这是应用服务的职责。目标是确保没有垃圾或有害数据进入系统。
  • 保护模型不变量。这是您的域逻辑。每当域中的某些内容发生更改时,您需要确保更改在您的域中有效,即所有不变量仍然有效。

验证域不变量作为应用服务的一部分

请注意,有时您还想验证应用服务中的域不变量。如果您需要将不变的违规行为传达回客户端,这可能是必要的。在域中执行此操作会使您的域逻辑特定于客户端,这不是您想要的。

在这种情况下,您需要注意域逻辑不会泄漏到应用服务中。 Specification Pattern 是克服此问题并同时使域和应用程序服务都可以访问业务规则的一种方法。

到另一个显示规范模式示例实现的问题。

而不是 "validating hat a required property has some value in it" 在域的外围,我更愿意确保它 can never become null 域的第一位。

您可以通过强制该实体的构造函数、工厂和方法的消费者始终传递 属性 的值来实现。

话虽这么说,您也可以在应用程序级别和表示层执行它(如今大多数 Web 应用程序框架都提供了方便的检查方法)。 2 或 3 次验证比一次更好。但是域应该是一致性的主要来源。