我正在(重新)设计大型应用程序,我们使用基于 DDD 的多层架构。
我们有带有数据层(存储库的实现)、域层(域模型和接口的定义 - 存储库、服务、工作单元)、服务层(服务的实现)的 MVC。到目前为止,我们在所有层中都使用域模型(主要是实体),并且我们仅将 DTO 用作视图模型(在控制器中,服务返回域模型,控制器创建视图模型,并将其传递给视图)。
我读过无数关于使用、不使用、映射和传递 DTO 的文章。我知道没有任何明确的答案,但我不确定是否可以将域模型从服务返回到控制器。如果我返回域模型,它仍然永远不会传递给视图,因为控制器总是创建特定于视图的视图模型——在这种情况下,它似乎是合法的。另一方面,当领域模型离开业务层(服务层)时感觉不对。有时服务需要返回域中未定义的数据对象,然后我们必须将新对象添加到未映射的域中,或者创建 POCO 对象(这很丑陋,因为有些服务返回域模型,有些有效地返回 DTO)。
问题是 - 如果我们严格使用视图模型,是否可以将域模型一直返回到控制器,或者我们是否应该始终使用 DTO 与服务层进行通信?如果是这样,是否可以根据服务需求调整域模型?(坦率地说,我不这么认为,因为服务应该消耗域所拥有的。)如果我们应该严格遵守 DTO,它们是否应该在服务层中定义?(我想是的。)有时很明显我们应该使用 DTO(例如,当服务执行大量业务逻辑并创建新对象时),有时很明显我们应该只使用域模型(例如,当会员服务返回贫血用户( s) - 创建与域模型相同的 DTO 似乎没有多大意义) - 但我更喜欢一致性和良好实践。
免责声明:我不打算使用任何设计模式,因为它存在并且很花哨,另一方面,我想使用好的设计模式和实践也因为它有助于设计整个应用程序,有助于分离担心,即使使用特定模式不是“必要的”,至少目前如此。
领域模型离开业务层(服务层)感觉不对劲
让你觉得你正在拉出胆量,对吗?根据 Martin Fowler 的说法:服务层定义了应用程序的边界,它封装了域。换句话说,它保护了域。
有时服务需要返回域中未定义的数据对象
你能提供这个数据对象的例子吗?
如果我们要严格遵守 DTO,是否应该在服务层中定义它们?
是的,因为响应是您的服务层的一部分。如果它被定义为“其他地方”,则服务层需要引用该“其他地方”,为您的千层面添加一个新层。
是否可以将域模型一直返回到控制器,或者我们是否应该始终使用 DTO 与服务层进行通信?
DTO 是一个响应/请求对象,如果您将它用于通信,则它是有意义的。如果您在表示层中使用域模型(MVC- Controllers/View、WebForms、ConsoleApp),那么表示层与您的域紧密耦合,域中的任何更改都需要您更改控制器。
创建与域模型相同的 DTO 似乎没有多大意义)
这是 DTO 对新人来说的缺点之一。现在,您正在考虑 重复代码 ,但是随着项目的扩展,它会更有意义,特别是在不同团队被分配到不同层的团队环境中。
DTO 可能会给您的应用程序增加额外的复杂性,但您的层也是如此。DTO 是您系统的一项昂贵功能,它们不是免费的。
本文提供了使用 DTO 的优点和缺点, http ://guntherpopp.blogspot.com/2010/09/to-dto-or-not- to-dto.html
总结如下:
何时使用
何时不使用
反对 DTO 的论据
与 DTO 的争论