这 3 种 DDD 分层架构的模式,你掌握了么?

这 3 种 DDD 分层架构的模式,你掌握了么?

–     DDD 的基本概念     –

DDD(Domain DrivenDesign,领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高质量的软件模型。在正确实现的情况下,我们通过DDD完成的设计恰恰就是软件的工作方式。

UL(Ubiquitous Language,通用语言)是团队共享的语言,是DDD中最具威力的特性之一。不管你在团队中的角色如何,只要你是团队的一员,你都将使用UL。由于UL的重要性,所以需要让每个概念在各自的上下文中是清晰无歧义的,于是DDD在战略设计上提出了模式BC(BoundedContext,限界上下文)。UL和BC同时构成了DDD的两大支柱,并且它们是相辅相成的,即UL都有其确定的上下文含义,而BC中的每个概念都有唯一的含义。

一个业务领域划分成若干个BC,它们之间通过Context Map进行集成。BC是一个显式的边界,领域模型便存在于这个边界之内。领域模型是关于某个特定业务领域的软件模型。通常,领域模型通过对象模型来实现,这些对象同时包含了数据和行为,并且表达了准确的业务含义。

从广义上来讲,领域即是一个组织所做的事情以及其中所包含的一切,表示整个业务系统。由于“领域模型”包含了“领域”这个词,我们可能会认为应该为整个业务系统创建一个单一的、内聚的和全功能式的模型。然而,这并不是我们使用DDD的目标。正好相反,领域模型存在于BC内。

在微服务架构实践中,人们大量地使用了DDD中的概念和技术:

  • 微服务中应该首先建立UL,然后再讨论领域模型。

  • 一个微服务最大不要超过一个BC,否则微服务内会存在有歧义的领域概念。

  • 一个微服务最小不要小于一个聚合,否则会引入分布式事务的复杂度。

  • 微服务的划分过程类似于BC的划分过程,每个微服务都有一个领域模型。

  • 微服务间的集成可以通过Context Map来完成,比如ACL(Anticorruption Layer,防腐层)。

  • 微服务间最好采用Domain Event(领域事件)来进行交互,使得微服务可以保持松耦合。

  • ……

这 3 种 DDD 分层架构的模式,你掌握了么?

–     模式一:四层架构     –

Eric Evans在《领域驱动设计-软件核心复杂性应对之道》这本书中提出了传统的四层架构模式,如下图所示:

这 3 种 DDD 分层架构的模式,你掌握了么?
  • 1. User Interface为用户界面层(或表示层),负责向用户显示信息和解释用户命令。这里指的用户可以是另一个计算机系统,不一定是使用用户界面的人。

  • 2. Application为应用层,定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题。这一层所负责的工作对业务来说意义重大,也是与其它系统的应用层进行交互的必要渠道。应用层要尽量简单,不包含业务规则或者知识,而只为下一层中的领域对象协调任务,分配工作,使它们互相协作。它没有反映业务情况的状态,但是却可以具有另外一种状态,为用户或程序显示某个任务的进度。

  • 3. Domain为领域层(或模型层),负责表达业务概念,业务状态信息以及业务规则。尽管保存业务状态的技术细节是由基础设施层实现的,但是反映业务情况的状态是由本层控制并且使用的。领域层是业务软件的核心,领域模型位于这一层。

  • 4. Infrastructure层为基础实施层,向其他层提供通用的技术能力:为应用层传递消息,为领域层提供持久化机制,为用户界面层绘制屏幕组件,等等。基础设施层还能够通过架构框架来支持四个层次间的交互模式。传统的四层架构都是 限定型松散分层架构 ,即Infrastructure层的任意上层都可以访问该层(“L”型),而其它层遵守 严格分层架构

笔者在四层架构模式的实践中,对于分层的本地化定义主要为:

  • 1. User Interface层主要是Restful消息处理,配置文件解析,等等。

  • 2. Application层主要是多进程管理及调度,多线程管理及调度,多协程调度和状态机管理,等等。

  • 3. Domain层主要是领域模型的实现,包括领域对象的确立,这些对象的生命周期管理及关系,领域服务的定义,领域事件的发布,等等。

  • 4. Infrastructure层主要是业务平台,编程框架,第三方库的封装,基础算法,等等。

说明:严格意义上来说,User Interface指的是用户界面,Restful消息和配置文件解析等处理应该放在Application层,User Interface层没有的话就空缺。但User Interface也可以理解为用户接口,所以将Restful消息和配置文件解析等处理放在User Interface层也行。

这 3 种 DDD 分层架构的模式,你掌握了么?

object-role-dir.png

  1. DCI中的Context层从Domain层上移变成Context层。

    因此,DDD分层架构模式就变成了五层,如下图所示:

这 3 种 DDD 分层架构的模式,你掌握了么?

ddd-l5.png

笔者在实践中,将这五层的本地化定义为:

  • 1. User Interface是用户接口层,主要用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给Application层的接口。

  • 2. Application层是应用层,负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当调度层收到用户接口层的请求后,委托Context层与本次业务相关的上下文进行处理。

  • 3. Context是环境层,以上下文为单位,将Domain层的领域对象cast成合适的role,让role交互起来完成业务逻辑。

  • 4. Domain层是领域层,定义领域模型,不仅包括领域对象及其之间关系的建模,还包括对象的角色role的显式建模。

  • 5. Infrastructure层是基础实施层,为其他层提供通用的技术能力:业务平台,编程框架,持久化机制,消息机制,第三方库的封装,通用算法,等等。

DDD五层架构模式讨论完了吗事还没有结束……

笔者参与的很多DDD落地实践,都是面向控制面或管理面且消息交互比较多的系统。这类系统的一次业务,包含一组同步消息或异步消息构成的序列,如果都放在Context层,会导致该层的代码比较复杂,于是我们考虑:

  • 1. Context层在面向控制面或管理面且消息交互比较多的系统中又分裂成两层,即Context层和大Context层。

  • 2. Context层处理单位为Action,对应一条同步消息或异步消息。

  • 3. 大Context层对应一个事务处理,由一个Action序列组成,一般通过Transaction DSL实现,所以我们习惯把大Context层叫做Transaction DSL层。

  • 4. Application层在面向控制面或管理面且消息交互比较多的系统中经常会做一些调度相关的工作,所以我们习惯把Application层叫做Scheduler层。

因此,在面向控制面或管理面且消息交互比较多的系统中,DDD分层架构模式就变成了六层,如下图所示:

这 3 种 DDD 分层架构的模式,你掌握了么?

ddd-l6.png

笔者在实践中,将这六层的本地化定义为:

  • 1. User Interface是用户接口层,主要用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给Scheduler层的接口。

  • 2. Scheduler是调度层,负责多进程管理及调度、多线程管理及调度、多协程调度和维护业务实例的状态模型。当调度层收到用户接口层的请求后,委托Transaction层与本次操作相关的事务进行处理。

  • 3. Transaction是事务层,对应一个业务流程,比如UE Attach,将多个同步消息或异步消息的处理序列组合成一个事务,而且在大多场景下,都有选择结构。万一事务执行失败,则立即进行回滚。当事务层收到调度层的请求后,委托Context层的Action进行处理,常常还伴随使用Context层的Specification(谓词)进行Action的选择。

  • 4. Context是环境层,以Action为单位,处理一条同步消息或异步消息,将Domain层的领域对象cast成合适的role,让role交互起来完成业务逻辑。环境层通常也包括Specification的实现,即通过Domain层的知识去完成一个条件判断。

  • 5. Domain层是领域层,定义领域模型,不仅包括领域对象及其之间关系的建模,还包括对象的角色role的显式建模。

  • 6. Infrastructure层是基础实施层,为其他层提供通用的技术能力:业务平台,编程框架,持久化机制,消息机制,第三方库的封装,通用算法,等等。

事务层的核心是事务模型,事务模型的框架代码一般放在基础设施层。关于事务模型,笔者以前分享过一篇文章—  《Golang事务模型》 ,感兴趣的同学可以看看。

综上所述,DDD六层架构可以看做是DDD五层架构在特定领域的变体,我们统称为DDD五层架构,而DDD五层架构与传统的四层架构类似,都是限定型松散分层架构 。

这 3 种 DDD 分层架构的模式,你掌握了么?

六边形每条不同的边代表了不同类型的端口,端口要么处理输入,要么处理输出。对于每种外界类型,都有一个适配器与之对应,外界通过应用层API与内部进行交互。上图中有3个客户请求均抵达相同的输入端口(适配器A、B和C),另一个客户请求使用了适配器D。假设前3个请求使用了HTTP协议(浏览器、REST和SOAP等),而后一个请求使用了AMQP协议(比如RabbitMQ)。

端口并没有明确的定义,它是一个非常灵活的概念。无论采用哪种方式对端口进行划分,当客户请求到达时,都应该有相应的适配器对输入进行转化,然后端口将调用应用程序的某个操作或者向应用程序发送一个事件,控制权由此交给内部区域。应用程序通过公共API接收客户请求,使用领域模型来处理请求。

我们可以将DDD战术设计的建模元素Repository的实现看作是持久化适配器,该适配器用于访问先前存储的聚合实例或者保存新的聚合实例。正如图中的适配器E、F和G所展示的,我们可以通过不同的方式实现资源库,比如关系型数据库、基于文档的存储、分布式缓存或内存存储等。如果应用程序向外界发送领域事件消息,我们将使用适配器H进行处理。该适配器处理消息输出,而上面提到的处理AMQP消息的适配器则是处理消息输入的,因此应该使用不同的端口。

我们在实际的项目开发中,不同层的组件可以同时开发。当一个组件的功能明确后,就可以立即启动开发。由于该组件的用户有多个,并且这些用户的侧重点不同,所以需要提供多个不同的接口。同时,这些用户的认识也是不断深入的,可能会多次重构相关的接口。于是,组件的多个用户经常会找组件的开发者讨论这些问题,无形中降低了组件的开发效率。

我们换一种方式,组件的开发者在明确了组件的功能后就专注于功能的开发,确保功能稳定和高效。组件的用户自己定义组件的接口(端口),然后基于接口写测试,并不断演进接口。在跨层集成测试时,由组件开发者或用户再开发一个适配器就可以了。

这 3 种 DDD 分层架构的模式,你掌握了么?

–     总结     –

本文先和读者一起回顾了DDD和分层架构的相关知识,然后将DDD分层架构中常用的三种模式(四层架构、五层架构和六边形架构)结合实践经验分别进行详细阐述,使得读者深刻理解DDD分层架构模式,以便在微服务的开发实践中根据具体情况选择最合适的DDD分层架构模式,从而交付结构清晰且易维护的软件产品。

来源:

https://www.jianshu.com/p/a775836c7e25

往期推荐

欧创新:深度解析DDD中台和微服务设计

领域驱动专家张逸文字脱口秀:简单工厂不简单

DDD专家张逸:《解构领域驱动设计》前言

Hacker News热文:请停止学习框架,学习领域驱动设计(DDD)(获500个点赞)

京东平台研发朱志国:领域驱动设计(DDD)理论启示

DDD专家张逸:构建领域驱动设计知识体系

领域驱动设计(DDD)在美团点评业务系统的实践

当DDD遇上微服务

DDD战略篇:架构设计的响应力

可视化与领域驱动设计

领域驱动设计(DDD)前夜:面向对象思想

领域驱动设计(DDD):领域和子域

DDD专家张逸:复杂与架构演进的关系

滕云:DDD实现之路

这 3 种 DDD 分层架构的模式,你掌握了么?

点个在看,让更多人看见

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92167 人正在系统学习中

来源:普通网友

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年2月26日
下一篇 2021年2月26日

相关推荐