4

我读过的一些关于 DDD 的文章表明,应用层中的应用服务或命令 (CQRS) 密切反映了特定的用例。

对于简单的用例,这种映射是有意义的,但在需要多个用户交互的更复杂的实例中,我试图了解如何映射 API 的课程粒度级别,而不将应用程序逻辑推送到 UI 中。

示例: - 想象一个应用程序服务:

ImportProductData(date_source)
  • 从系统/用户界面的角度来看,在导入产品数据时,我们要检查是否有任何产品已经存在,如果存在,则在继续之前提示用户是否要继续。

我常用的方法:扩展 API 以包括:

DoesIncludeExistingProducts(data_source)

如果返回 true,则提示用户是否要继续,然后调用。

ImportProductData(date_source, overwrite=True)

我的问题是这是否会将大部分应用程序逻辑转移到 UI 层?(即UI现在控制是否可以覆盖产品,以及在导入产品数据之前是否应检查现有产品等)

如果是,我无法想象应用程序层和域层将如何处理这个问题?除了:

来电:

ImportProductData(date_source)

如果失败,检查失败的原因,如果由于产品已经存在,提示用户并再次调用:

ImportProductData(date_source, overwrite=True)

这感觉就像做与上述相同的事情的不同方式。

这可能看起来有点迂腐,但我正在努力使表示层 (MVC) 尽可能轻薄。

关于任何更优雅的解决方案的想法?


4

2 回答 2

2

首先在这里查看 Jimmy Bogards 的启发性帖子https://jimmybogard.com/domain-command-patterns-validation/。他没有回答你的问题,而是以一种可以让你更容易下定决心的方式攻击它。

在那篇文章中,他简要地谈到了我认为需要更多关注的一点。如果“用户经常尝试做我的域验证不允许的事情”,他建议不要使用异常作为通信机制。使用这个标准,我更喜欢将预期有时会失败的用例分解为验证调用,然后是执行调用。

在您的情况下,使用 IsProductSetValidForImport 之类的验证查询(不是命令)似乎是合适的。在上面 Jimmy 的文章中,他努力决定返回的错误集应该有多丰富,但是查询的返回集应该是丰富的,所以我们没有问题。您可以返回一个真实的、完全形成的视图模型来显示给用户,而不是尝试将足够的数据塞进错误字符串中来绘制屏幕。我假设如果 10 个产品中有 3 个无法导入,您可能希望允许用户强制更新某些产品而不是其他产品。这给了你这个机会。

如果这个验证查询没有返回冲突,给用户一个“你确定”的消息,然后调用 API 来执行导入命令。如果在调用验证查询和发出更新命令之间发生了一些重要的状态变化,那么引发异常并处理后果是合适的。

于 2018-06-12T12:09:01.777 回答
1

在用户发出真正的命令来做一些可能会改变事情的事情之前,您不应该访问 ApplicationServices。

是什么阻止了您在 MVC 表示模式中让控制器使用 ViewServices 层来完成您所要求的事情?

于 2018-06-12T09:49:56.380 回答