小编典典

服务应该总是返回 DTO,还是它们也可以返回域模型?

all

我正在(重新)设计大型应用程序,我们使用基于 DDD 的多层架构。

我们有带有数据层(存储库的实现)、域层(域模型和接口的定义 - 存储库、服务、工作单元)、服务层(服务的实现)的
MVC。到目前为止,我们在所有层中都使用域模型(主要是实体),并且我们仅将 DTO
用作视图模型(在控制器中,服务返回域模型,控制器创建视图模型,并将其传递给视图)。

我读过无数关于使用、不使用、映射和传递 DTO
的文章。我知道没有任何明确的答案,但我不确定是否可以将域模型从服务返回到控制器。如果我返回域模型,它仍然永远不会传递给视图,因为控制器总是创建特定于视图的视图模型——在这种情况下,它似乎是合法的。另一方面,当领域模型离开业务层(服务层)时感觉不对。有时服务需要返回域中未定义的数据对象,然后我们必须将新对象添加到未映射的域中,或者创建
POCO 对象(这很丑陋,因为有些服务返回域模型,有些有效地返回 DTO)。

问题是 - 如果我们严格使用视图模型,是否可以将域模型一直返回到控制器,或者我们是否应该始终使用 DTO
与服务层进行通信?如果是这样,是否可以根据服务需求调整域模型?(坦率地说,我不这么认为,因为服务应该消耗域所拥有的。)如果我们应该严格遵守
DTO,它们是否应该在服务层中定义?(我想是的。)有时很明显我们应该使用
DTO(例如,当服务执行大量业务逻辑并创建新对象时),有时很明显我们应该只使用域模型(例如,当会员服务返回贫血用户( s) - 创建与域模型相同的 DTO
似乎没有多大意义) - 但我更喜欢一致性和良好实践。

免责声明:我不打算使用任何设计模式,因为它存在并且很花哨,另一方面,我想使用好的设计模式和实践也因为它有助于设计整个应用程序,有助于分离担心,即使使用特定模式不是“必要的”,至少目前如此。


阅读 86

收藏
2022-05-24

共1个答案

小编典典

领域模型离开业务层(服务层)感觉不对劲

让你觉得你正在拉出胆量,对吗?根据 Martin Fowler 的说法:服务层定义了应用程序的边界,它封装了域。换句话说,它保护了域。

有时服务需要返回域中未定义的数据对象

你能提供这个数据对象的例子吗?

如果我们要严格遵守 DTO,是否应该在服务层中定义它们?

是的,因为响应是您的服务层的一部分。如果它被定义为“其他地方”,则服务层需要引用该“其他地方”,为您的千层面添加一个新层。

是否可以将域模型一直返回到控制器,或者我们是否应该始终使用 DTO 与服务层进行通信?

DTO 是一个响应/请求对象,如果您将它用于通信,则它是有意义的。如果您在表示层中使用域模型(MVC-
Controllers/View、WebForms、ConsoleApp),那么表示层与您的域紧密耦合,域中的任何更改都需要您更改控制器。

创建与域模型相同的 DTO 似乎没有多大意义)

这是 DTO 对新人来说的缺点之一。现在,您正在考虑 重复代码 ,但是随着项目的扩展,它会更有意义,特别是在不同团队被分配到不同层的团队环境中。

DTO 可能会给您的应用程序增加额外的复杂性,但您的层也是如此。DTO 是您系统的一项昂贵功能,它们不是免费的。

为什么使用 DTO

本文提供了使用 DTO 的优点和缺点, http ://guntherpopp.blogspot.com/2010/09/to-dto-or-not-
to-dto.html

总结如下:

何时使用

  • 对于大型项目。
  • 项目寿命为10年及以上。
  • 战略、任务关键型应用程序。
  • 大型团队(5人以上)
  • 开发人员在地理上分布。
  • 领域和表现形式不同。
  • 减少开销数据交换(DTO 的初衷)

何时不使用

  • 中小型项目(最多 5 名成员)
  • 项目寿命为2年左右。
  • GUI、后端等没有单独的团队。

反对 DTO 的论据

与 DTO 的争论

  • 没有 DTO,表示和域是紧密耦合的。(这对于小型项目来说是可以的。)
  • 接口/API 稳定性
  • 可以通过返回仅包含绝对需要的那些属性的 DTO 来为表示层提供优化。使用linq-projection,您不必拉出整个实体。
  • 为了降低开发成本,使用代码生成工具
2022-05-24