DDD / CQRS - 请求处理程序(或控制器)是否可以抛出在域级别定义的异常?

DDD / CQRS - Does a request handler (or controller) can throw exceptions defined at the domain level?

早上好,

比方说,我们有一个定义异常的域,例如 ObjectNotFoundException,它需要一个在域模型中定义的标识符 (VO)。

问题

我们能否直接从请求处理程序中抛出域异常,例如:

    class ObjectRequestHandler implements RequestHandler
    {
        ...

        public function __invoke(Request $request, Response $response)
        {
            // Will self-validate and throw an exception if not a valid UUID
            $objectId = ObjectId::fromString(strval($request->param('object_id'])));

            $object = $this->repository->find((string)$objectId);

            if (NULL === $object) {
                // Exception defined at the domain level...
                throw new ObjectNotFoundException($objectId);
            }

            ...
        }
}

这样做也会导致在请求处理程序中使用标识符 VO...必须 还要注意抛出的异常将被默认的异常处理程序捕获反过来,将准备并发送 JSON 响应。

最后,请注意这里的请求处理程序是一个实现细节,而不是问题的一部分。请勿评论。

谢谢。

您的示例显示了存储库根据标识符从数据存储中获取对象的正确用法。

让我们进一步解压缩和扩展工作流以适应 DDD 的范例,以帮助回答问题:

  • API 控制器(或请求处理程序)将使用被调用方发送的请求参数调用应用程序服务。
  • 转发给应用服务的请求参数可以是简单数据(如JSON)也可以是对象(如DTO)
  • 应用程序服务可以访问与对象关联的正确存储库。
  • 存储库在领域层之外
  • 在将控制权移交给域层(或在域层中调用方法)之前,应用程序服务会使用这些存储库将对象加载到内存中。
  • 如果没有找到给定标识符的对象,通常会从存储库中抛出 ObjectNotFound 错误
  • 域层通常从应用程序服务接收它需要处理的所有对象或使用工厂方法构建对象。
  • 实际过程都是根据业务规则分配或转换属性值,同时确保满足不变规则。所以领域层抛出的错误类型是业务规则错误(或验证错误)。

所以,

  • ObjectNotFoundException 不是域异常
  • 您尚未处于域级别,因此将标识符称为 ValueObject 是不正确的

暂时忽略应用程序服务,您对概念的使用很准确。代码示例在结构上是正确的。只是需要澄清的术语。