背景:为了我自己的清晰/自我教育,我尝试使用TDD + DDD实现一个简单的订单输入应用程序。我的主要目标是通过分离关注点来保持体系结构的整洁。
我有四层(现在).
此外,我想在关键层之间通过POCO DTO.特别是在Persistence=>Domain层和ApplicationFacade=>Presentation层之间。因此,我有CustomerDto、OrderDto、OrderItemDto,它们在共享包中定义了适当的关系。
我希望使用Constructor注入将ICustomerRepository的实现注入客户“业务实体”类,然后调用“业务实体”上的Customer.Save()来启动创建/更新过程,最终调用CustomerRepository上的Save。毕竟,客户是“聚合根”,拥有保存所需的所有信息.它也是注入CustomerRepository的“守护者”。
问题:,这是我遇到麻烦的地方。我希望尽可能保持域/BLL层的纯净,避免将其耦合到任何第三方框架和APIs,但是 Customer.Save()方法需要将客户“聚合根”及其所有订单和OrderItems转换为DTO版本,以便传输到注入的持久性层CustomerRepository .这是Automapper的工作。
问题是..。如果我不把Automapper放在域/BLL层中,我就不太确定应该去哪里。
即使它的工作是业务流程,把它放在ApplicationFacade中也是不对的。
把它放在域/BLL层肯定感觉不对,因为我想让它保持原始状态。
所以我觉得我错过了什么..。我在处理这个问题时,对工作部分应该如何聚集在一起来完成这个任务产生了根本性的误解。有什么建议吗?(请温柔一点,我对这一切都是新的,也是新的。请告诉我是否需要向您展示我目前所拥有的代码。)
发布于 2012-12-08 21:12:51
为了回答您的具体问题,我将更广泛地介绍您的体系结构。您为项目设计的体系结构与DDD所使用的典型体系结构有着微妙的不同。虽然划分责任的方式是典型的,但在DDD中,域类并不对自己的持久性负责。事实上,DDD的口号是persistence ignorance。这基本上意味着域类是持久化无知的--它们没有Save
方法。相反,应用程序服务(体系结构中的应用程序外观层)与存储库协调,以重建和持久化域实体。
其次,在实现存储库时,在底层持久性技术和域类之间通常不需要显式的DTO。使用诸如NHibernate和EF这样的or,域类和关系表之间的映射可以用映射类或基于XML的配置来表示。因此,您的域类被隐式映射--不需要DTO。有些情况下确实需要DTO,在这种情况下,DTO和域类之间的映射应该由存储库实现封装。这是一个可以调用AutoMapper的地方。
最后,在表示层和应用程序/域层之间使用DTO进行通信是一种常见的做法。要准确地确定映射应该在哪里进行,您必须深入了解最适合您的项目的体系结构。大多数现代DDD架构都是基于Hexagonal architecture的。在六角体系结构中,您的域位于中心位置,所有其他“层”都使域适应特定的技术。例如,存储库可以看作是域和特定数据库技术之间的一个adapter。ASP.NET WebAPI可以看作是域和HTTP之间的适配器。同样,表示层可以看作是域和特定域之间的适配器。DTO可以在每个适配器中显化,适配器有责任映射到和从这些DTO中映射。
一个典型的例子是使用应用程序服务在域上建立外观。目前还没有DTO发挥作用。接下来,使用ASP.NET WebAPI (一个适配器)创建一个服务层(在DDD中打开主机服务)。您可以创建特定于ASP.NET WebAPI的DTO,这取决于此适配器来映射这些DTO。因此,如果您使用AutoMapper,则应该在此层调用它。这可以显式地完成,也可以使用动作过滤器以aspect-oriented方式完成。表示层也是如此。表示层可以直接耦合到应用程序服务,或者直接耦合到ASP.NET WebAPI开放主机服务。在这两种情况下,表示层都有责任在域类(来自应用程序服务或来自WebAPI的DTO)和它自己的原语(如ViewModel )之间映射。
https://stackoverflow.com/questions/13772177
复制相似问题