我的应用程序遵循DDD设计原则。它是一个ASP.NET MVC应用程序,MVC应用程序是表示层(我将控制器移到了应用层)。它还具有主要是应用程序服务、用例等的应用层。应用层之上是域模型驻留的域层。然后是基础架构层,它位于所有其他层的顶部,并且应该不依赖于其他层。
但我注意到一个问题,如果持久化逻辑像DDD书中建议的那样进入基础架构层,那么基础架构层将依赖于域层。例如,存储库需要知道要创建的域模型(实体)的类型,有了这些知识,它们就会依赖于域层。然而,最初的DDD原则建议基础架构层应该完全不依赖任何东西。
所以现在我很困惑,持久性逻辑真的应该属于基础设施层吗?如果是这样的话,它会使基础架构层依赖于域层。如果不是,那么它应该放在哪里?应用层?或者在应用层和域层之间建立一个单独的层(因为应用程序服务使用存储库,所以存储库使用域模型)。你认为如何?
发布于 2016-10-16 17:41:57
依赖关系的类型
我认为在这里可能会有帮助的一个重要概念是区分依赖的类型-具体地说,一个层或组件可以依赖于另一个层,因为:
Inversion of Control和Dependency Injection使得这一区别变得更加重要。他们引导我们应该依赖于抽象而不是具体。
这意味着,例如,域层可以定义并依赖于存储库的抽象-例如IEntityRepository接口。
但是,实现(具体化)随后在基础架构层实现。
当应用层想要调用存储库时,它依赖于抽象(接口),控制反转系统(IoC容器)为它提供来自基础架构层的实现。
在这种情况下,基础架构层依赖于域层-只是为了了解它正在实现的接口,而不是为了委托给它而依赖于任何其他层-它是调用堆栈中的最后一层。
这个概念解决了您所关心的冲突,因为基础架构层不依赖于任何其他东西来执行其功能。
洋葱架构
一旦您开始将IoC概念融入到体系结构的思考中,一个非常有用的模型就是onion architecture模式。在这个视图中,我们保留了分层方法,而不是将其视为堆栈,而是将其视为分层的洋葱,域位于中心,与应用程序外部的一切交互位于边缘。
最初的DDD书籍没有特别提到这一点,但它已经成为实现DDD系统的一种非常常见的模式。
它也称为Ports and Adaptor模式或Hexagonal Architecture。
这个想法是,它根据洋葱的“了解”来建模依赖关系-外层知道内层,而内层不知道外层。
但它根据洋葱上的移动对应用程序流的委托进行建模-从洋葱的一边到另一边。
更具体地说:
外层(也称为“主适配器”)是请求进入系统的地方。适配器负责处理特定的API表示(例如REST api),并将其转换为对应用程序服务层(下一层)的请求。这通常表示为洋葱的左上角。
应用程序服务层表示应用程序的“用例”。通常,方法将使用存储库接口来检索聚合的实例,然后委托给聚合根上的方法来执行业务逻辑,该业务逻辑涉及根据用例的需要更改聚合的状态。然后,应用程序服务层使用另一个接口来要求基础架构层“保存”更改(通常使用工作抽象单元)
在这里,我们让应用层将控制流委托给洋葱的“外层”(也称为“辅助适配器”)。这通常被表示为洋葱的右下角,类似于您描述中的“基础设施层”。
这就是IoC的用武之地。因为我们有一个委托给外层的内层,所以这是可能的,因为外层已经实现了在内层中定义的接口(它可以这样做,因为它知道内层)。但是,IoC容器注入了实际的具体实现,从而有效地允许内层将控制委托给外层,而不依赖于它。
在这种概念化中,请求从左上角流向右下角,而内部层对外层一无所知。
发布于 2016-10-15 19:37:09
这里有两个选项
1)使用DAO对象。然后,基础架构层只需要知道这些DAO对象。特别是如果你使用实体框架或类似的东西,那么这是一个不错的策略。您确实从映射中获得了一些开销,但是您可以使用Automapper来实现。
2)接受这样一个事实,即基础设施知道您的DDD模型。但是,由于DDD中的一切都是围绕您的域模型进行的,所以这并不是一个很糟糕的折衷方案。(特别是如果您的域模型非常容易理解,因此不会发生根本性的变化)。但是要非常小心,不要让你的域模型因为数据库设计而受到影响。应该始终是数据库跟随,而不是域模型,因为很难在数据库中迁移,所以您不能对其进行特定的更改。
发布于 2017-02-21 02:00:04
持久性逻辑通常属于基础架构层,它位于洋葱的外层,由于洋葱的外层依赖于内部层,而域层位于中心,那么是的,基础架构层依赖于域层。
https://stackoverflow.com/questions/40054807
复制相似问题