
写在前面:
朋友你好,今天我想与你聊一聊,DDD概念复杂、难懂,实际落地该怎么设计代码实现模型。关于这个话题,先说说整体框架、思路,我打算结合两部分分享给你,每一部分,相信仔细看完,都会或多或少有所收获。以下内容,预计1分钟左右可快速看完:
前一部分, 方法篇 ,旨在详细介绍DDD所包含的几个核心概念,以及围绕这些概念所构建的DDD代码实现模型的组成结构。
至于为何有必要讲,开头我会明确告诉大家;这部分,咱们暂且不论你所处的具体是哪个技术领域/方向,日常工作中,你一定遇到过有些复杂又难懂的概念吧,没搞清楚的时候,想将它们落实到具体的开发工作中去,就难了。看完这一篇,将会帮助你掌握如何基于复杂概念设计系统架构的方法。
后半部分, 实践篇 , 预计于明天傍晚发布, 到时得空了可继续看,进一步思考。我继续接着说,承接前面内容,要想让这些代码实现模型真正落地,我们需要把它们与具体的应用场景结合起来。我将侧重详细阐述DDD代码实现模型的设计方法,并给出一个具体的案例分析。
关于看这一话题的方式,我觉得倒也不妨提上一嘴,建议你可以后续两篇结合着思考。考虑到大家可能一般都是碎片化时间来看的,到时看完这一方法篇,希望你可以带着或多或少的疑问,明天更有针对性地接着看实践篇。若当时来不及细看,倒也不妨花上短短几分钟,大体过一遍。相较而言,相信你也可以对此话题的理解程度、思考的深浅度等层面,更有益,思维也更开阔。
责编 | 韩楠
约 2973 字 | 4 分钟阅读
以下,Enjoy~
伴随着业务系统 复杂度的不断提升,以及微服务架构等分布式技术体系的大行其道,领域驱动设计(Domain Driven Design,DDD),日渐成为系统建模领域的主流设计思想和模式。在DDD中,引入了限界上下文、聚合、实体、值对象、领域事件、资源库、应用服务等一系列核心概念。
通过这些概念,开发人员可以开展系统设计和实现工作。但是,DDD中的这些概念相对都比较抽象,甚至有些晦涩难懂。再往相通或类似问题点上靠,我认为实质上对于复杂难懂的概念的理解和把握,我们一开始不必过于纠结这些概念本身,而是可以把它们与现实中的具体实现模型对应起来。
通过两者之间的合理映射,来促进对概念本身的理解,如下图所示。这里多说一句,即便你是其他技术领域的朋友,或许也曾遇到过类似问题,并有着共通性。希望看完今天的分享,可以或多或少帮助到你,并有所启发、思考。

在上图中,我们一方面尝试把复杂概念映射到实现模型。另一方面,基于对实现模型的把握,可以反推对复杂概念的理解程度,从而更好地掌握这些概念。这也更足以见得实践才能出真知,也只有设计过实现模型,才能真正掌握这些概念,从而把它们应用到各种具体的场景中。
这是一种行之有效的办法。
那么问题就来了,在日常开发过程中,如何确保DDD真正落地,把这些抽象概念转为具体代码模式,是我们今天要讨论的内容。
01 ⎪
想设计代码实现模型, 咱非得了解DDD中这几个核心概念?
总体来说,DDD提供的是一种 开展业务建模和软件设计的方法论。DDD认为良好的系统架构,应该是技术架构和业务架构相互融合的结果,开发人员不能脱离业务领域来设计技术架构。为了实现这一目标,DDD提出了一组核心概念,如图1所示。

图1
我们先来看第一个核心概念,就比较难于理解,即限界上下文(Boundary Context)。在DDD中,当我们把业务领域拆分成多个子域之后,限界上下文明确了子域的 业务界限 ,并实现子域与子域之间的隔离,如图2所示。

图2
有了限界上下文,我们就需要围绕业务场景设计领域模型对象(Domain Model Object)。领域模型对象,包含了 丰富的业务逻辑和操作行为 ,这点和只包含数据属性的传统数据对象,有本质区别。
因此,领域模型对象是我们在应用DDD时, 最应该关注的一组对象,也是最难把握的一组对象。
在DDD中,领域模型对象包括三大类,即聚合(Aggregate)、实体(Entity)和值对象(Value Object),这三类对象各有特点。

图3
相较领域模型对象,领域事件诞生较晚,但也是领域模型的一个重要组成部分,因为现实中很多场景,都可以抽象成事件(Event),如图4。

图4
在DDD中,通过领域事件可以实现 业务状态变化的有效传播,并在单个限界上下文内部或在多个上下文之间,对这些状态变化做出响应。
业务领域中的各种状态变化最终都需要进行存储。为此,DDD提供了一个针对业务数据的 统一访问入口,这就是资源库(Repository)。通过资源库,我们可以实现对各种领域对象的持久化操作,如图5所示。

图5
最后,我们来引入应用服务的概念。应用服务包括 命令(Command)服务和查询(Query) 服务两大类,本质上起到的是一种解耦和协调作用,确保各种领域模型对象之间的交互和协作。因此,在 涉及到多个限界上下文之间的交互时,我们需要重点关注应用服务。如图6所示。

图6
02 ⎪
概念复杂又难懂,想实际业务场景下真正落地,需引入DDD代码实现模型
关于DDD中的核心概念,我就简单介绍到这里,
下一步就是要讨论一个所有开发人员都必须面对的话题,即如何将这些复杂难懂的概念,在现实的开发过程中能够真正落地?
这就需要引入DDD代码实现模型。
▶︎ 要想设计代码实现模型,先得搞清楚它有哪几部分组成?
无论设计方法有多好, 能够转换为可运行的代码才是王道,这点对于DDD而言尤为如此。
可惜的是,目前业界关于如何实施这些概念,并没有一套统一的标准和规范,这就导致我们在具体的开发过程中,常常感到无从下手。为此,本文 专门提炼了一整套DDD代码实现模型。接下来,让我们从DDD代码实现模型的基本概念和组织结构展开讨论。
▶︎ 在讲代码实现模型之前,先弄清楚什么是实现模型
说起模型(Model),业界主流的方法论认为存在三种不同的类型,即领域模型、设计模型和代码模型,如图7所示。

图7
关于领域模型,我们在前面的内容中已经做了介绍。在DDD中,聚合、实体、值对象、领域事件等,都可以归属到这一模型的范畴。
而设计模型(Design Model),可以分成边界模型和内部模型两个组成部分。边界模型明确系统边界,抽象系统集成和交互方案。而内部模型细化边界模型,在明确系统边界的前提下,实现系统内部模块和组件的抽象和构建。因此,在DDD中,我们往往 从限界上下文的角度出发,来开展设计模 型的建设 ,如下图所示。

图8
最后,代码模型为现实世界的解决方案,提供可执行的系统环境。我们可以通过在领域模型和设计模型中嵌入代码的方式来构建代码模型,该模型是将 DDD各个复杂概念转换为可执行代码的关键所在,也是我们今天要讨论的主要内容。
显然,领域模型、设计模型和代码模型之间,存在一种层次依赖关系,如图 9所示。
首先,领域模型代表领域的固有业务;
设计模型指向领域模型,关注对外部接口的承诺以及交互关系;
代码模型提供了完整实现过程,是对设计模型的细化。
正是通过这三种 模型的整合,完成了从现实问题到最终能够落地的实现方案的演进。

图9
▶︎ DDD代码实现模型,应包含哪些部分?
针对DDD代码实现模型的讨论,我们也将遵循上述三种模型的整合过程。结合DDD中的各种核心概念,我们梳理DDD代码实现模型组成结构,如图10所示。

图10
在上图中,我们可以清晰看到DDD代码实现模型的四个组成部分,分别面向领域对象、应用服务、基础设施以及上下文集成。讲到这里,你可能会问, 为什么我们要这样设计DDD的代码实现模型呢?
我们知道一个完整的DDD应用程序,通常由多个限界上下文构成。因此,对于代码实现模型而言,我们需要 重点考虑两个维度,即:
-
单个限界上下文实现过程中的代码模型
-
多个限界上下文之间集成过程中的代码模型
在上图中,关于领域对象、应用服务、基础设施代码实现模型的讨论,属于单个限界上下文的范畴,而上下文实现代码集成模型,显然面向多个限界上下文,如图11所示。

图11
通过前面内容的学习,相信你对DDD代码实现模型的组成结构,已了然在胸。
那么,在日常开发过程中,我们应该如何设计这些代码实现模型呢?有没有具体的案例可以参考呢?这几个问题点,你可以先停下来琢磨下。
下一讲 ,也希望你可以带着或多或少的疑问来。我将继续结合此话题有针对性地展开,与你聊一聊实践相关的。
感谢你看到了这里,同时期待明天,以及后续的某几个时段里,我与你能够有更多思想上的交流、碰撞。如果愿意分享,这一讲也欢迎转发给你的朋友,和他一起讨论。
好了,今天就说到这里,我们明天见。