DDD学习笔记---进阶篇

DDD学习笔记---进阶篇_第1张图片

 

领域事件

用来表示领域中发生的事件。

举例来说的话,领域事件可以是业务流程的一个步骤,比如投保业务缴费完成后,触发投保单转保单的动作;也可能是定时批处理过程中发生的事件,比如批处理生成季缴保费通知单,触发发送缴费邮件通知操作;或者一个事件发生后触发的后续动作,比如密码连续输错三次,触发锁定账户的动作。

领域事件相关案例

DDD学习笔记---进阶篇_第2张图片

事件起点:客户购买保险 - 业务人员完成保单录入 - 生成投保单 - 启动缴费动作。

1. 投保微服务生成缴费通知单,发布第一个事件:缴费通知单已生成,将缴费通知单数据发布到消息中间件。收款微服务订阅缴费通知单事件,完成缴费操作。缴费通知单已生成,领域事件结束。

2. 收款微服务缴费完成后,发布第二个领域事件:缴费已完成,将缴费数据发布到消息中间件。原来的订阅方收款微服务这时则变成了发布方。原来的事件发布方投保微服务转换为订阅方。投保微服务在收到缴费信息并确认缴费完成后,完成投保单转成保单的操作。缴费已完成,领域事件结束。

3. 投保微服务在投保单转保单完成后,发布第三个领域事件:保单已生成,将保单数据发布到消息中间件。保单微服务接收到保单数据后,完成保单数据保存操作。保单已生成,领域事件结束。

4. 保单微服务完成保单数据保存后,后面还会发生一系列的领域事件,以并发的方式将保单数据通过消息中间件发送到佣金、收付费和再保等微服务,一直到财务,完后保单后续所有业务流程。这里就不详细说了。

领域事件运行机制相关案例

这个领域事件发生在投保和收款微服务之间。缴费通知单已生成-------------> 缴费。

DDD学习笔记---进阶篇_第3张图片

事件起点:出单员生成投保单,核保通过后,发起生成缴费通知单的操作。

1. 投保微服务应用服务,调用聚合中的领域服务 createPaymentNotice 和 createPaymentNoticeEvent,分别创建缴费通知单、缴费通知单事件。其中缴费通知单事件类 PaymentNoticeEvent 继承基类 DomainEvent。

2. 利用仓储服务持久化缴费通知单相关的业务和事件数据。为了避免分布式事务,这些业务和事件数据都持久化到本地投保微服务数据库中。

3. 通过数据库日志捕获技术或者定时程序,从数据库事件表中获取事件增量数据,发布到消息中间件。这里说明:事件发布也可以通过应用服务或者领域服务完成发布。

4. 收款微服务在应用层从消息中间件订阅缴费通知单事件消息主题,监听并获取事件数据后,应用服务调用领域层的领域服务将事件数据持久化到本地数据库中。

5. 收款微服务调用领域层的领域服务 PayPremium,完成缴费。

DDD分层架构

什么是 DDD 分层架构?

DDD 的分层架构在不断发展。最早是传统的四层架构;后来四层架构有了进一步的优化,实现了各层对基础层的解耦;再后来领域层和应用层之间增加了上下文环境(Context)层,五层架构(DCI)就此形成了。

DDD学习笔记---进阶篇_第4张图片

我们看一下上面这张图,在最早的传统四层架构中,基础层是被其它层依赖的,它位于最核心的位置,那按照分层架构的思想,它应该就是核心,但实际上领域层才是软件的核心,所以这种依赖是有问题的。后来我们采用了依赖倒置(Dependency inversion principle,DIP)的设计,优化了传统的四层架构,实现了各层对基础层的解耦。

xiDDD 分层架构就是优化后的四层架构

DDD学习笔记---进阶篇_第5张图片

DDD 分层架构最重要的原则是什么?

在《实现领域驱动设计》一书中,DDD 分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合。

DDD 分层架构如何推动架构演进?

1.微服务架构的演进

通过基础篇的讲解,我们知道:领域模型中对象的层次从内到外依次是:值对象、实体、聚合和限界上下文。

实体或值对象的简单变更,一般不会让领域模型和微服务发生大的变化。但聚合的重组或拆分却可以。这是因为聚合内业务功能内聚,能独立完成特定的业务逻辑。那聚合的重组或拆分,势必就会引起业务模块和系统功能的变化了。

这里我们可以以聚合为基础单元,完成领域模型和微服务架构的演进。聚合可以作为一个整体,在不同的领域模型之间重组或者拆分,或者直接将一个聚合独立为微服务。

DDD学习笔记---进阶篇_第6张图片

我们结合上图,以微服务 1 为例,讲解下微服务架构的演进过程:

  • 当你发现微服务 1 中聚合 a 的功能经常被高频访问,以致拖累整个微服务 1 的性能时,我们可以把聚合 a 的代码,从微服务 1 中剥离出来,独立为微服务 2。这样微服务 2 就可轻松应对高性能场景。
  • 在业务发展到一定程度以后,你会发现微服务 3 的领域模型有了变化,聚合 d 会更适合放到微服务 1 的领域模型中。这时你就可以将聚合 d 的代码整体搬迁到微服务 1 中。如果你在设计时已经定义好了聚合之间的代码边界,这个过程不会太复杂,也不会花太多时间。
  • 最后我们发现,在经历模型和架构演进后,微服务 1 已经从最初包含聚合 a、b、c,演进为包含聚合 b、c、d 的新领域模型和微服务了。

2.微服务内服务的演进

DDD学习笔记---进阶篇_第7张图片

我们看下上面这张图。在服务设计时,你并不一定能完整预测有哪些下层服务会被多少个上层服务组装,因此领域层通常只提供一些原子服务,比如领域服务 a、b、c。但随着系统功能增强和外部接入越来越多,应用服务会不断丰富。有一天你会发现领域服务 b 和 c 同时多次被多个应用服务调用了,执行顺序也基本一致。这时你可以考虑将 b 和 c 合并,再将应用服务中 b、c 的功能下沉到领域层,演进为新的领域服务(b+c)。这样既减少了服务的数量,也减轻了上层服务组合和编排的复杂度。

那我们该怎样转向 DDD 分层架构呢?不妨看看下面这个过程。

传统企业应用大多是单体架构,而单体架构则大多是三层架构。三层架构解决了程序内代码间调用复杂、代码职责不清的问题,但这种分层是逻辑概念,在物理上它是中心化的集中式架构,并不适合分布式微服务架构。

DDD学习笔记---进阶篇_第8张图片

首先,你要清楚,三层架构向 DDD 分层架构演进,主要发生在业务逻辑层数据访问层

DDD 分层架构在用户接口层引入了 DTO,给前端提供了更多的可使用数据和更高的展示灵活性。

DDD 分层架构将业务逻辑层的服务拆分到了应用层和领域层。应用层快速响应前端的变化,领域层实现领域模型的能力。

三层架构数据访问采用 DAO 方式;DDD 分层架构的数据库等基础资源访问,采用了仓储(Repository)设计模式,通过依赖倒置实现各层对基础资源的解耦。

仓储又分为两部分:仓储接口和仓储实现。仓储接口放在领域层中,仓储实现放在基础层。原来三层架构通用的第三方工具包、驱动、Common、Utility、Config 等通用的公共的资源类统一放到了基础层。

微服务架构模型:几种常见模型的对比和分析

整洁架构

整洁架构又名“洋葱架构”。

在整洁架构里,同心圆代表应用软件的不同部分,从里到外依次是领域模型、领域服务、应用服务和最外围的容易变化的内容,比如用户界面和基础设施。

整洁架构最主要的原则是依赖原则,它定义了各层的依赖关系,越往里依赖越低,代码级别越高,越是核心能力。外圆代码依赖只能指向内圆,内圆不需要知道外圆的任何情况。

DDD学习笔记---进阶篇_第9张图片

在洋葱架构中,各层的职能是这样划分的:

  • 领域模型实现领域内核心业务逻辑,它封装了企业级的业务规则。领域模型的主体是实体,一个实体可以是一个带方法的对象,也可以是一个数据结构和方法集合。
  • 领域服务实现涉及多个实体的复杂业务逻辑。
  • 应用服务实现与用户操作相关的服务组合与编排,它包含了应用特有的业务流程规则,封装和实现了系统所有用例。
  • 最外层主要提供适配的能力,适配能力分为主动适配和被动适配。主动适配主要实现外部用户、网页、批处理和自动化测试等对内层业务逻辑访问适配。被动适配主要是实现核心业务逻辑对基础资源访问的适配,比如数据库、缓存、文件系统和消息中间件等。
  • 红圈内的领域模型、领域服务和应用服务一起组成软件核心业务能力。

六边形架构

六边形架构又名“端口适配器架构”。追溯微服务架构的渊源,一般都会涉及到六边形架构。

六边形架构的核心理念是:应用是通过端口与外部进行交互的

也就是说,在下图的六边形架构中,红圈内的核心业务逻辑(应用程序和领域模型)与外部资源(包括 APP、Web 应用以及数据库资源等)完全隔离,仅通过适配器进行交互。它解决了业务逻辑与用户界面的代码交错问题,很好地实现了前后端分离。六边形架构各层的依赖关系与整洁架构一样,都是由外向内依赖。

DDD学习笔记---进阶篇_第10张图片

六边形架构将系统分为内六边形和外六边形两层,这两层的职能划分如下:

  • 红圈内的六边形实现应用的核心业务逻辑;
  • 外六边形完成外部应用、驱动和基础资源等的交互和访问,对前端应用以 API 主动适配的方式提供服务,对基础资源以依赖倒置被动适配的方式实现资源访问。

三种微服务架构模型的对比和分析

虽然 DDD 分层架构、整洁架构、六边形架构的架构模型表现形式不一样,但你不要被它们的表象所迷惑,这三种架构模型的设计思想正是微服务架构高内聚低耦合原则的完美体现,而它们身上闪耀的正是以领域模型为中心的设计思想。

DDD学习笔记---进阶篇_第11张图片

请你重点关注图中的红色线框,它们是非常重要的分界线,这三种架构里面都有,它的作用就是将核心业务逻辑与外部应用、基础资源进行隔离。

领域层实现面向领域模型,实现领域模型的核心业务逻辑,属于原子模型,它需要保持领域模型和业务逻辑的稳定,对外提供稳定的细粒度的领域服务,所以它处于架构的核心位置。

用层实现面向用户操作相关的用例和流程,对外提供粗粒度的 API 服务。它就像一个齿轮一样进行前台应用和领域层的适配,接收前台需求,随时做出响应和调整,尽量避免将前台需求传导到领域层。应用层作为配速齿轮则位于前台应用和领域层之间。

从三种架构模型看中台和微服务设计

中台本质上是领域的子域,它可能是核心域,也可能是通用域或支撑域。通常大家认为阿里的中台对应DDD的通用域,将通用的公共能力沉淀为中台,对外提供通用共享服 

中台作为子域还可以继续分解为子子域,在子域分解到合适大小,通过事件风暴划分限界上下文以后,就可以定义微服务了,微服务用来实现中台的能力。表面上看,DDD、中台、微服务这三者之间似乎没什么关联,实际上它们的关系是非常紧密的,组合在一起可以作为一个理论体系用于你的中台和微服务设计。

中台

阿里提出中台战略后,很多企业开始拿着自己的系统与阿里的中台对标。有的企业在十多年前就完成了大一统的集中式系统拆分,实现了从传统大单体应用向大平台的演进,他们将公共能力和核心能力分开建设,解决了公共模块重复投入和重复建设的问题。

阿里业务中台的前身是共享平台,而原来的共享平台更多的被当作资源团队,他们承接各业务方的需求,并为业务方在基础服务上做定制开发。 阿里业务中台的目标是把核心服务链路(会员、商品、交易、营销、店铺、资金结算等)整体当作一个平台产品来做,为前端业务提供的是业务解决方案,而不是彼此独立的系统。

下面我们分析一下传统企业大平台战略和阿里中台战略的差异。

平台只是将部分通用的公共能力独立为共享平台。虽然可以通过 API 或者数据对外提供公共共享服务,解决系统重复建设的问题,但这类平台并没有和企业内的其它平台或应用,实现页面、业务流程和数据从前端到后端的全面融合,并且没有将核心业务服务链路作为一个整体方案考虑,各平台仍然是分离且独立的。

平台解决了公共能力复用的问题,但离中台的目标显然还有一段差距!

中台到底是什么?

先看一下阿里自己人对中台的定义:“中台是一个基础的理念和架构,我们要把所有的基础服务用中台的思路建设,进行联通,共同支持上端的业务。业务中台更多的是支持在线业务,数据中台提供了基础数据处理能力和很多的数据产品给所有业务方去用。业务中台、数据中台、算法中台等等一起提供对上层业务的支撑。”

再看一下思特沃克对中台的定义:“中台是企业级能力复用平台。

中台来源于平台,但中台和平台相比,它更多体现的是一种理念的转变,它主要体现在这三个关键能力上:对前台业务的快速响应能力企业级复用能力;从前台、中台到后台的设计、研发、页面操作、流程服务和数据的无缝联通、融合能力

其中最关键的是快速响应能力和企业级的无缝联通和融合能力,尤其是对于跨业经营的超大型企业来说至关重要。

后台

很多人提到中台时自然会问:“既然有前台和中台,那是否有后台,后台的职责又是什么?”

我们来看一下阿里对前台、中台和后台的定位。

前台主要面向客户以及终端销售者,实现营销推广以及交易转化;中台主要面向运营人员,完成运营支撑;后台主要面向后台管理人员,实现流程审核、内部管理以及后勤支撑,比如采购、人力、财务和 OA 等系统。

DDD、中台和微服务:它们是如何协作的?

中台是抽象出来的业务模型,微服务是业务模型的系统实现,DDD 作为方法论可以同时指导中台业务建模和微服务建设,三者相辅相成,完美结合。

中台在企业架构上更多偏向业务模型,形成中台的过程实际上也是业务领域不断细分的过程。在这个过程中我们会将同类通用的业务能力进行聚合和业务重构,再根据限界上下文和业务内聚的原则建立领域模型。而 DDD 的战略设计最擅长的就是领域建模。

中台的本质其实就是提炼各个业务板块的共同需求,进行业务和系统抽象,形成通用的可复用的业务模型,打造成组件化产品,供前台部门使用。前台要做什么业务,需要什么资源,可以直接找中台,不需要每次都去改动自己的底层。

你可能感兴趣的:(领域驱动设计,java,开发语言,后端)