戏说领域驱动设计(十三)——核心架构

  在做了两章铺垫后本章再续写第九章。我们之前介绍过了好几种架构模式,那么本章只挑一种往死了整,这个架构其实就是在DDD书中所介绍的经典四层的变更版。这里面需要注意一点,四层架构是洋葱架构的一部分,尽管洋葱型已经是微服务架构系统中一种事实上的标准,但我们不会对各类适配器做重点介绍,那些东西一般都是开源的组件或者没有业务逻辑的组件比如DAO。再说了,您都已经学习DDD了还需要我再讲解什么是DAO吗?所以我们只介绍下面图形中绿色边界内部的东西。

一、基于CQS的ODD风格分层架构

  四层架构实际上更多的用于面向对象(也可称之为对象驱动式)编程,如果是面向过程其实经典三层就够了。下面图展示了一个典型的四层架构的构成及各层间的访问限制。如果您看过DDD相关的经典书籍会发现此图和书上的并不一致,主要原因有两点:1)省略了视图层,那个不是我们的重点;2)资源库实现理论上属于基础设施层,而我们在这里进行分开是因为这个组件比较核心,我见过较多的案例都是把资源库误当DAO用,所以需要在此重点提出来讲解。本来我这个系列文章就充满了个性,咱们直面开发中的各类痛点会提供大量的干货而不是和其它文章一样都含糊的带过去。

  上图,如果将“资源库”和“基础设施”二合一,您再根据依赖关系就能推导出来这是一个典型的洋葱架构。再加上比如RESTful、MQ等适配器就是六边型架构。这回您知道为什么我说洋葱和六边型其实是一个东西的不同叫法了吧?除了层的结构信息,访问顺序也是您需要重点关注的内容,如果违反了约束所谓的洋葱也就不成立了(比如让领域模型转而依赖基础设施,那领域模型就不再是架构中的核心了)。还有一点需要说明,在一个服务中(Service)通常会包含两种不同的架构模式:查询模式架构和命令模式架构,上图属于命令模式,查询请参考下图。一般来说查询架构相对要简单的很多,使用经典三层开发模式即可。

 

  根据上面两图所示:在同一个服务中使了两种不同的架构模式,分别为Command端(简称C端)和Query端(简称Q端)),这种方法可称之为命令查询分离(CQS,请注意与CQRS作好区分)模式,这样的区分会大大提升系统的开发效率和运行效率。由于查询操作并不会修改数据也不会包含业务逻辑,所以工程师只需要面向“系统运行性能”即可,也就是查询怎么快怎么来,层数少自然开发的速度也快,也可以把一些优化手段应用于查询相关的代码中而不用考虑事务、一致性、对象封装等各种条条框框的约束。而命令模式中,其要考虑的内容多、代码更加的严谨。不说别的,仅参数验证就够喝一壶的了(我也见过有些开发从不做参数验证,依赖于前端的正确性判定。我跟你说,别说前端了,各包之间的调用都是不可信任的,所以验证每个参数的合法性是必需甚至是强制的)……。

  C端架构图中还标识了序号,表示设计的先后顺序或编写代码的顺序。由于我们使用的是洋葱架构,领域模型层必然要最先设计;紧接着自然是应用服务层,包参数验证、组织业务流程控制、存取领域模型、发布命令或事件等操作。注意,虽然此时尚没有设计数据持久化等功能,但您别忘了资源库的接口是在领域模型层定义出来的,所以是可以直接在应用服务中引用的,如果用的是Spring框架则可直接注入进来;第三个要做的工作是数据访问层的设计包括DAO和数据模型,这一层您需要根据领域模型的特性和当前系统的基础设施条件来决策使用什么样的后端存储。最后要设计的是资源库实现层,这东西负责把领域模型与数据模型互转及领域模型的事务化存储。Q端的设计顺序正好与C端相反,先设计DAO再考虑应用服务,也就是先着重查询效率再考虑数据出去前的加工。这两个设计模型的顺序限制目前并无现成的理论作支撑,应该是一种个人的最佳实践,您可以考虑在项目中实验一下,这个顺序其实也符合了上一章说的先模型后服务的建议原则。

  虽然C端和Q端两个图并不是很精确,但仍然突出了厚度的不同。C端的领域模型层占比较大,Q端的应用服务层则更为厚重一点(厚重不代表要先设计,只表示其会组织查询逻辑比如数据的合并等,并非和DAO一样只单纯的关注数据的查询)。

二、再续六边形架构

  很多DDD强调了六边形架构,但到目前为止我们在这方面并未投入过多的讲解,主要是因为时机不成熟,而有了4层架构作为基础则是最好的机会。我先贴一张《实现领域驱动设计》中关于六边型的示意图。同原图不同,我在这个图的上面画了一条橙色的竖线,作用后面说。参照咱们前面的内容相信就可以揭开这个架构的神秘面纱了。继续阅读前请您注意,这里的六边型是针对每一个限界上下文而不是整个系统。

  首先,我们使用橙色的线把这个图分成了两部分,竖线左边是应用程序的输入端,右边当然就是输出了,而所有用于输入和输出的都称之为适配器。

  分割后,应用程序这个小六边结构不变,是系统的核心。左边的适配器是应用程序的输入端口,如果是微服务架构自然就是RESTful、gRPC等接口层;如果是微前端就是UI层;如果需要接收MQ,自然就是消息监听组件。右边适配器是为应用服务提供输出能力,如果使用了数据库,当然就是DAO组件;如果需要发送MQ就是消息发送组件。六边型架构在现在的系统中其实非常常见,您现在系统可能就是这个架构只是不知道它名字罢了。而基于微服务架构的系统,甚至可以认为其中的每一个服务都是六边型的。讲到此处有一点需要说明:DDD书中的六边型强调了领域模型部分,而我认为这一部分是可选的,要视业务的复杂度而定。

  作为六边型的核心,应用程序不能一笔带过。如果使用了对象驱动的方式,其架构自然就是上面我们所讲的四层模式;如果是事务脚本,一般无业务模型的概念,因为您的业务已经集中于应用程序服务之中了。实际上现在有很多人反对事务脚本,认为使用了事务脚本其架构就不能称之为六边型。 但我个人认为六边型是一种思想,它强调了业务应居于系统的核心,事务脚本不代表业务是分散的。此外,我们应该从业务的角度来决策架构选型而不是过份的强调技术,这个思想会贯穿本系列文章。还有一点您记住了,不论书中写的多么天花乱坠,给的永远只是参考和指导,具体哪些可以用到工作中需要进行取舍。

  相信通过上面的讲解,您就会发现所谓的六边型也没什么了不起的,也搞不好会感叹一下:就这 ?

总结

  本章详细介绍了4层架构的结构、访问顺序以及设计顺序;同时,对六边型架构(也就是洋葱架构)做了补充性说明,相信您已经明白书上和网上常说的六边型是什么意思了。后面我们继续对4层架构进行深入讲解包括各类领域模型的作用以及一些代码案例。

posted @ 2022-03-14 10:55  SKevin  阅读(984)  评论(0编辑  收藏  举报