回答一下前两天一位读者的问题:DDD中,为什么是基础层反向依赖领域层。
对于这个问题,工具人是这么理解的:逻辑上其实是领域层依赖了基础设施层。比如:领域模型变更后,需要保存到数据库、发送到MQ等等。但是在代码实现中,往往却是基础设施层依赖于领域层。
这句话怎么理解呢?因为,在架构设计的时候,一般都会遵循一些共同模式,不管是六边形架构、还是洋葱圈架构等等,都提倡以业务为核心,解耦外部依赖,分离业务复杂度和技术复杂度等。通俗地说,就是越是核心的逻辑,依赖应该越少。在DDD中,最核心的就是领域模型了。
在以往的MVC分层架构中,我们的核心业务逻辑是在Service层中编排的,而Service往往依赖于DAO层或其它技术实现。当我们需要做一些无关业务逻辑的优化时,比如给某个事件同步一下缓存、或者发送到一个MQ等,就需要去改动Service,这是因为业务的实现依赖于具体的技术,使得技术的变动反过来影响到了核心业务。
在DDD的模式中,我们往往采用依赖倒置等方式,做到业务实现于技术实现分离。
依赖倒置原则具体包括:
1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。
2、抽象不应该依赖于细节,细节应该依赖于抽象。
在DDD中体现在:
1,domain层作为上层模块,不依赖于下层的infrastructure层;
2,domain层中的细节,依赖于repository的抽象(所以repository的接口被放置在domain中),而repository的具体实现放在了infrastructure中。并通过依赖注入的模式将具体技术实现动态加载到domain中。而infrastructure作为底层模块,可以依赖于domain层。
这样就避免了MVC分层架构中的依赖问题,保留了抽象(领域模型)的稳定性的同时,并提供了基础设施的灵活性。
接下来,我们举个六边形架构的例子:

在传统的分层架构中,我们所有的依赖项都会指向一个方向,上面的每一层都会依赖自己下面的层。
在六边形架构中,所有依赖项都指向中心方向。其中,中间的entity对应着DDD中的domain层。我们的核心业务逻辑对传输层或数据源一无所知。
该架构由端口和适配器组成。所谓端口,就是应用的入口和出口,在许多语言中,它以接口的形式存在。而适配器则用来屏蔽端口细节,其主要分为两种:1,主动适配器代表用户如何访问应用,从技术上来说,它们接收用户输入,调用端口并返回输出。2,被动适配器实现应用的出口端口,向外部工具执行操作。
若将其可视化,主动适配器和被动适配器基于端口围绕着应用形成左右结构,有别于传统的分层形象,形成一个六边形,因此也会称作六边形架构。
所以在DDD中,我们所谓的Repository和分层架构中的定位,与分层架构中的DAO有着本质的区别,Repository是被动适配器的一种抽象,而不仅仅是用于对于数据库的操作的接口封装。
好了,今天工具人就写到这里,比较仓促,如有不对的地方,请大家多多指正。




