3

创建只包含对象的命令是否有意义?例如:

public class CreateCommand : IRequest
{
   SomeDTO SomeDTO { get; set; }
}

public class UpdateCommand : IRequest
{
   SomeDTO SomeDTO { get; set; }
}

或者可能是这样的(推导):

public class UpdateCommand : SomeDTO, IRequest
{
}

或者命令/请求本身应该被视为 DTO?我很困惑,因为我看到了很多做事的方法。将所有属性复制到命令/请求类听起来也不是一件好事。

你如何在你的项目中做到这一点?

你是直接将你的命令映射到你的领域模型,还是仅仅为了传递 DTO 而使用命令?

如果使用 MVC 框架,我的控制器操作的输入应该是什么?它应该是一个命令,还是应该在我的操作实现中创建命令并发送它?(我想这将取决于我如何建模我的命令)

4

3 回答 3

3

创建只包含对象的命令是否有意义?

不,额外的类没有任何价值:没有语义,没有行为......

或者命令/请求本身应该被视为 DTO?

命令(在CQRS术语的意义上)本质上是 DTO。它们是在层/层之间循环的哑数据包。

您是否将命令直接映射到域模型

这取决于您是否更喜欢基于任务的 UI而不是基于 CRUD 的 UI。如果你做 DDD/富域模型——有些人甚至会说基本的 OO 封装——你不会映射它们。命令名称可能会匹配实体方法,但它们的内容不会自动映射到域模型字段。

如果使用 MVC 框架,我的控制器操作的输入应该是什么?它应该是一个命令,还是应该在我的操作实现中创建命令并发送它?

我会说两者都是合法且适用的,除了 MVC 模型绑定的偶尔技术怪癖。

于 2018-06-18T12:37:31.570 回答
2

至少在我的世界中,命令和域对象具有不同的设计约束。特别是,命令是 API 表面的一部分——它们是与其他服务的合同的一部分——因此需要在很长一段时间内具有兼容的定义。另一方面,域对象是我们当前做事方式的本地对象——它们是我们黑匣子内数据组织的一部分。所以我们可以以任何我们喜欢的节奏改变那些。

跨越进程边界的命令是消息,也就是说byte[]s。这一点需要在形式和语义上保持稳定。

byte[]与域无关,并且在“解析”消息时通过其他几个与域无关的中间阶段是相当常见的

byte[] -> utf8
utf8 -> DOM
DOM -> Dictionary
...

但我们通常会朝着合同的特定领域表达方向发展。

参见,例如Mark Seemann

在边界上,应用程序不是面向对象的。DTO 是映射到面向对象语言中的此类数据的表示。

强制byte[]转换成便于查询的形式,我们可以开始考虑是否要使用该数据来开始初始化“对象”。

您可能会问的另一个问题 - 将消息数据包含在通用元数据“信封”中是否有价值。这种模式一直在发生——最熟悉的例子是 HTTP POST 是一组附加到消息体的通用标头。

数据和元数据当然是不同的关注点;在您的解决方案中保持它们的区别绝对是有意义的。

我认为组合数据结构,而不是继承它们,将是更易于维护的选择。

public class Envelope<Message> ....

可能是一个合理的起点。

于 2018-06-18T12:30:54.563 回答
0

您应该将该命令视为指示您的域做某事的“口头语句”。例如,“UpdateCommand”指示您的域更新某些内容。在命令中,您应该包含命令的详细信息(在您的情况下 dto 很好)...

但是要非常小心那些 DTO。您不希望您的域依赖于 MVC,反之亦然。确保 dto 所在的程序集的级别(在 MVC 的方向上)不高于域逻辑。

在您的 MVC 中,您应该只有:

  • 依赖注入设置
  • 控制器和视图

控制器应该只包含从方法(http)参数(女巫是不安全的)转换为域所需的 dto 并调用域所需的代码。

至少我是这样做的。

于 2018-06-18T12:20:01.190 回答