DDD 让人感觉晦涩难懂,主要是因为DDD诞生之初,是一个纯粹的理论体系,它包含了各种复杂且难以理解的概念,它那一堆名词与理论,让人看起来很费力。
今天我们来直击其本质,让你快速上手DDD 领域驱动设计,let's go!
1、什么是 DDD
DDD(Domain-Driven Design,领域驱动设计)是一种软件设计方法,专注于通过深入理解业务领域来构建复杂的软件系统。
DDD的核心思想是将业务需求与软件设计紧密结合,通过建立清晰的领域模型,使开发人员和业务人员能够以共同的语言交流,从而更好地解决业务问题。
简单理解:DDD 不是架构,而是一种架构设计方法论,它通过边界划分将复杂业务领域简单化,帮我们设计出清晰的领域和应用边界,可以很容易地实现架构演进。
提到「架构演进」,我们就不得不提软件架构模式的演进历程。
2、软件架构模式的演进
软件架构模式的演进历程是一个不断适应技术发展和业务需求变化的过程,主要经历以下三个阶段:
- 单机架构:采用面向过程的设计方法,系统包括客户端 UI 层和数据库两层,采用 C/S 架构模式,整个系统围绕数据库驱动设计和开发,并且总是从设计数据库和字段开始。
- 集中式架构:采用面向对象的设计方法,系统包括业务接入层、业务逻辑层和数据库层,采用经典的三层架构,也有部分应用采用传统的 SOA 架构。这种架构容易使系统变得臃肿,可扩展性和弹性伸缩性差。
当然也有部分资料,将「集中式架构」分解为垂直架构/烟囱式架构 + 面向服务的架构(SOA) 两部分
- 分布式微服务架构:随着微服务架构理念的提出,集中式架构正向分布式微服务架构演进。微服务架构可以很好地实现应用之间的解耦,解决单体应用扩展性和弹性伸缩能力不足的问题。
图片
DDD 是一种架构设计方法,微服务是一种架构风格。两者都是为了拆解业务复杂度:合理划分领域边界,持续调整现有架构,优化现有代码,以保持架构和代码的生命力,也就是我们常说的演进式架构。
3、DDD 核心概念
DDD领域设计模型的核心概念:
- 领域(Domain):业务问题的范围,是DDD领域设计模型的基础。
- 限界上下文(Bounded Context):明确划定的领域模型的边界,它定义了领域内词汇表和模型的范围,使得在同一限界上下文内的开发人员能够使用统一的语言进行交流。
- 实体(Entity):领域中的核心概念,具有唯一标识,并随时间变化其属性。实体在领域模型中通常表现为对象,具有业务逻辑和状态。
- 值对象(Value Object):描述事物的对象,没有唯一标识,主要用于描述领域中的某个方面或属性。值对象通常用于传递参数或对实体进行补充描述。
- 聚合(Aggregate):一组具有内聚关系的相关对象的集合,用于确保数据一致性。聚合根是聚合中的核心实体,负责维护聚合内部对象的一致性和完整性。
图片
如何来划定领域模型和微服务的边界呢?
可以分三步来搞定~ (*^▽^*)
- 第一步:在事件风暴中梳理业务过程中的用户操作、事件以及外部依赖关系等,根据这些要素梳理出领域实体等领域对象。
- 第二步:根据领域实体之间的业务关联性,将业务紧密相关的实体进行组合形成聚合,同时确定聚合中的聚合根、值对象和实体。在上图里,聚合之间的边界是第一层边界,它们在同一个微服务实例中运行,这个边界是逻辑边界,所以用虚线表示。
- 第三步:根据业务及语义边界等因素,将一个或者多个聚合划定在一个限界上下文内,形成领域模型。在上图里,限界上下文之间的边界是第二层边界,这一层边界可能就是未来微服务的边界,不同限界上下文内的领域逻辑被隔离在不同的微服务实例中运行,物理上相互隔离,所以是物理边界,边界之间用实线来表示。
4、DDD 架构模型
三层架构向 DDD 四层架构演进,主要发生在业务逻辑层和数据访问层。
图片
DDD 四层架构包含用户接口层、应用层、领域层和基础层。
通过这些层次划分,我们可以明确微服务各层的职能,划定各领域对象的边界,确定各领域对象的协作方式:
- 接口层(接入层、表示层)
职责:作为所有流量入口,负责接口定义和实现,同时还包括消息的监听以及job的触发入口。常见的接口类型包括grpc、http、mq、job等。
实践:在Web应用中,接口层通常包含Controller类,并按不同的客户端(如移动端、管理端、开放接口等)进行划分。
- 应用层
- 职责:负责流程编排和差异化能力路由。它接收用户请求,进行必要的校验和调度,然后转发给领域层处理,并将处理结果返回给用户。
- 实践:应用层通常包含服务编排类(如XxxAppService)、领域事件监听器(如XxxListener)、实体工厂(如XxxFactory)等。
- 领域层
- 职责:包含系统的核心业务逻辑和规则,是DDD架构的核心。领域层与具体技术无关,不依赖其他各层,确保了业务逻辑的独立性和可复用性。
- 实践:领域层按领域聚合进行划分,外部聚合按限界上下文(微服务)划分。它定义了充血模型、值对象、仓库接口、领域服务、领域事件等。领域契约(contract)包含API层特殊出入参、数据查询参数、领域事件等。
- 基础层
- 职责:与外部系统和资源交互,屏蔽外部特性,转化成应用内识别定义的数据类型。它负责持久化机制实现、通用技术支持等。
- 实践:基础设施层包含仓库层实现(如XxxRepositoryImpl)、外部服务实现(如封装外部系统接口的引用,防止腐化领域模型)等。
5、DDD 应用挑战
虽然 DDD 领域设计模型具备一些应用优势,但它毕竟不是银弹,同样存在一些应用挑战问题:
- 领域知识的获取:建立准确的领域模型需要深入的业务知识和对领域的深入理解。这可能需要与业务专家进行大量的沟通和交流。
- 模型的复杂性:随着业务领域的复杂性和规模的增加,领域模型可能会变得非常复杂和难以维护。
- 技术实现的挑战:DDD领域设计模型的具体实现需要考虑到具体的技术框架和平台,这可能会增加开发的难度和复杂性。
6、总结
整篇梳理下来,我觉得DDD不像一门技术,而更像是一种方法论,包含了很多设计理念。
知为行之始,行为知之成。准确做事的前提是准确的认知。
DDD领域设计模型是一种非常有效的软件设计方法,它可以帮助开发人员更好地理解业务领域,并开发出符合业务需求的软件系统。然而,在实际应用中,也需要考虑到领域知识的获取、模型的复杂性和技术实现的挑战等问题。