DDD领域驱动设计

DDD概述

DDD(领域驱动设计)是一种处理高度复杂领域的设计思想,是一种架构设计方法论,是一种设计模式。以高内聚低耦合为目的,把一个复杂的软件应用系统中各个部分进行一个很好的拆解和封装,对软件系统进行模块化的一种思想。DDD不仅可以用于微服务设计,还可以很好地应用于企业中台的设计,也适用于传统的单体应用。
领域驱动设计(Domain-Driven Design,简称DDD)是一种软件开发方法论,由Eric Evans在他的著作《领域驱动设计:软件核心复杂性应对之道》中详细阐述。DDD旨在通过关注领域本身及其复杂性,来创建灵活且可维护的软件系统。
Domain Driven Design(领域驱动设计, DDD),不是一种架构,而是一种架构方法论,是一种拆解业务、划分业务、确定业务边界的方法,是一种领域设计思想。
核心思想:建立领域模型,领域模型处于架构的核心位置。
核心目标:避免业务逻辑的复杂度与技术实现的复杂度混淆在一起。
DDD包括战术设计和战略设计两部分。
战略设计:侧重于高层次、宏观上去划分和集成限界上下文。
战术设计:关注更具体使用建模工具来细化上下文。
总的来说,领域驱动设计是一种以领域模型和业务需求为核心的软件设计方法,它可以帮助开发团队更好地理解和满足复杂的业务需求。

DDD详解

领域驱动设计(Domain-Driven Design,DDD)是一种软件开发方法论,其中领域模型是其中的核心概念之一。领域模型是对特定业务领域的抽象表示,它描述了领域中的概念、规则、行为和关系。领域模型通过使用面向对象的方式来组织和表达业务逻辑。
在领域驱动设计中,领域模型通常由实体(Entity)、值对象(Value Object)、聚合(Aggregate)、领域服务(Domain Service)等构成。

  1. 实体(Entity):代表具有唯一标识的有生命周期的对象,具有自身的属性和行为。可以通过标识来跟踪和区分不同的实体。
  2. 值对象(Value Object):用于表示没有唯一标识的对象,它们是不可变的,仅仅由它们的属性值来定义。通常用于传递数据或进行计算。
  3. 聚合(Aggregate):一组相关的实体和值对象的集合,聚合根(Aggregate Root)是聚合的入口点,负责维护聚合内部的一致性和完整性。
  4. 领域服务(Domain Service):表示领域中的操作和行为,它们通常是无状态的,提供一些跨实体的业务操作。
    领域模型通过对领域中的概念进行建模,使得开发人员和领域专家能够更好地理解和沟通业务需求,同时也为软件系统的实现提供了一个清晰而一致的结构。它能够帮助团队更好地理解和解决复杂的业务问题,并支持迭代、增量的开发方式
    DDD是一种强大的方法论,尤其适用于复杂领域的系统设计和开发。通过关注领域本身及其复杂性,DDD能够帮助开发团队构建灵活、可维护和符合业务需求的软件系统。要有效应用DDD,需要深刻理解领域、持续与领域专家沟通,并采用适当的设计模式和实践。

核心概念
领域(Domain)
领域是一个企业或组织的核心业务活动和概念。领域模型是对这些活动和概念的抽象表示。
限界上下文(Bounded Context)
限界上下文是一个明确的边界,定义了特定模型适用的范围。不同的限界上下文可以包含相同的术语,但在每个上下文中的含义可能不同。
实体(Entity)
实体是具有唯一标识的对象,其生命周期内的状态会发生变化。例如,客户、订单等。
值对象(Value Object)
值对象是没有唯一标识的对象,通常是不可变的。它们通过其属性值来表示,例如地址、货币等。
聚合(Aggregate)
聚合是一组相关的实体和值对象,它们作为一个单元一起被修改和访问。聚合根是聚合的入口点,负责维护聚合的一致性。
领域服务(Domain Service)
领域服务是一些不适合放在实体或值对象中的操作。它们通常是无状态的,包含领域逻辑。
工厂(Factory)
工厂是创建复杂对象或聚合实例的设计模式,封装了对象创建的复杂性。
仓储(Repository)
仓储是存储和检索聚合的设计模式,提供一种访问持久化数据的中介。

设计原则
以领域模型为核心
领域模型是开发过程中的核心,开发团队应围绕领域模型进行讨论和设计。
持续的领域专家参与
领域专家与开发团队持续沟通,确保模型正确反映业务需求和逻辑。
领域语言(Ubiquitous Language)
使用领域语言进行交流,这种语言由领域专家和开发人员共同定义,确保所有人对领域概念的理解一致。
上下文映射(Context Mapping)
上下文映射用于描述不同限界上下文之间的关系和交互方式。

实践
分层架构
通常DDD系统采用分层架构,包括用户界面层、应用层、领域层和基础设施层。
事件风暴(Event Storming)
事件风暴是一种发现和理解领域事件的方法,通过团队讨论和绘制事件图,识别领域中的关键行为和交互。
CQRS(Command Query Responsibility Segregation)
CQRS是一种将读取操作(查询)和写入操作(命令)分离的模式,提升系统性能和可伸缩性。
领域事件(Domain Event)
领域事件是对领域中发生的有意义的事件的建模,用于在限界上下文之间传递信息和触发行为。

在这里插入图片描述

在这里插入图片描述

领域驱动设计应用场景是什么

善于处理高复杂业务的产品研发、可帮助我们提炼稳定的产品内核(领域模型中称为核心域);
2) 通过建模可提高建模高内聚、降低模型间的耦合度,提高系统的可扩展性与稳定性;
3) 强调团队与领域专家的合作沟通,有助于建立一个沟通良好的团队组织;
4) 统一设计思想与设计规范,有助于提高团队成员的架构设计能力和面向对象设计能力;
5) 现有的微服务建构都是遵循领域驱动设计的架构原则;
6) 如果你负责的软件系统并不复杂,那么,你确实不需要学习领域驱动设计

领域驱动设计跟时下流行的架构思维最大的区别是什么

在这里插入图片描述

传统的方案
三层应用架构:数据-应用(业务逻辑层)-展现,通常是以数据位为起点进行数据库分析设计。
1). 服务层过重,数据模型失血,没东西;
2). 面条式编程或者面向数据库编程,服务层围绕数据库作业完成业务逻辑,经常一条线撸到底;
3). 代码一整块一整块的过重,很难扩展复用;
4). 数据库模型只是数据库映射,没有相关的行为支撑,行为都被上一层Service给完成等了,因此是失血 的领域模型;

领域驱动方案
架构四层在DDD分层结构中将三层中业务逻辑拆解为应用层和领域层,核心业务逻辑表现下沉到领域层去实现,以业务领域模型为核心建模(面向对象建模),更能体现对现实世界的抽象,其优点如下
1). 轻服务层+充血的领域模型;
2). 领域模型封装和实现各自应有的行为,可以认为是一个高内聚、低耦合的组件;
3). 由于模型集数据与行为于一身,是一种自解释的对象,代码复用性高,业务逻辑清晰明确;
用户界面层:主要职责是通过用户界面向用户显示数据信息,同时解释用户的命令,并把用户的请求发送到应用层。
应用层:通过调用基础设置和领域层完成数据资源操作及业务流程编排,相当于BS层;
领域层:将业务逻辑高度内聚到领域层,所以领域层是整个系统的核心,它只与实际业务相关,不关心任何技术细节,尽可能做到与持久化无关;
基础设施层:包含了任何类型的框架、数据库访问代码或者公共的方法等,纯技术的一层;

在这里插入图片描述

DDD的充血模型和贫血模型的区别

在领域驱动设计(DDD)中,充血模型和贫血模型代表了两种不同的设计理念。

  1. 充血模型(Rich Domain Model):
    在充血模型中,领域对象(Domain Objects)承担了更多的责任和行为。这意味着领域对象不仅仅是数据的容器,还包含了业务逻辑和行为方法。
    充血模型鼓励将业务逻辑封装在领域对象内部,使得对象自身具有丰富的行为和状态。这种方式下,领域对象不仅仅是简单的数据结构,而是能够自主进行操作和决策的实体。
  2. 贫血模型(Anemic Domain Model):
    贫血模型则将更多的业务逻辑放在了外部的服务或者领域服务中,而领域对象本身主要作为数据的容器,缺乏丰富的行为。
    在贫血模型中,领域对象通常只包含数据,而行为逻辑则分散在应用程序的其他层中,例如服务层或者应用层。
    这种方式下,领域对象类似于被动的数据结构,缺乏自身的行为和逻辑。
    从DDD的角度来看,充血模型更符合领域驱动设计的核心理念,即将业务逻辑集中到领域对象中,使得领域对象成为系统中的活跃参与者。相比之下,贫血模型虽然也可以实现业务功能,但会导致业务逻辑分散、难以维护等问题。
    在领域驱动设计(DDD)中,充血模型和贫血模型代表了两种不同的设计理念。
    undefined 充血模型(Rich Domain Model):
    在充血模型中,领域对象(Domain Objects)承担了更多的责任和行为。这意味着领域对象不仅仅是数据的容器,还包含了业务逻辑和行为方法。
    充血模型鼓励将业务逻辑封装在领域对象内部,使得对象自身具有丰富的行为和状态。这种方式下,领域对象不仅仅是简单的数据结构,而是能够自主进行操作和决策的实体。
    undefined 贫血模型(Anemic Domain Model):
    贫血模型则将更多的业务逻辑放在了外部的服务或者领域服务中,而领域对象本身主要作为数据的容器,缺乏丰富的行为。
    在贫血模型中,领域对象通常只包含数据,而行为逻辑则分散在应用程序的其他层中,例如服务层或者应用层。
    这种方式下,领域对象类似于被动的数据结构,缺乏自身的行为和逻辑。
    从DDD的角度来看,充血模型更符合领域驱动设计的核心理念,即将业务逻辑集中到领域对象中,使得领域对象成为系统中的活跃参与者。相比之下,贫血模型虽然也可以实现业务功能,但会导致业务逻辑分散、难以维护等问题。

DDD(领域驱动设计)中的充血模型和贫血模型在设计和实现上存在显著的区别。以下是它们之间的主要区别,分点表示并进行归纳:
概念定义:
贫血模型(Anemic Domain Model):实体只包含数据属性和对应的getter以及setter方法,具体的业务逻辑交由服务层或其他外部组件负责。这种模型将数据与操作分离,使模型足够简单,开发上手较快。
充血模型(Rich Domain Model):实体不仅包含数据属性,还包含了引起属性发生变化的核心业务动作。这种模型将数据与业务能力绑定在一起,非常符合业务人员的思考方式。
业务逻辑处理:
贫血模型:所有的业务逻辑、规则验证、数据转换等操作都被移至业务逻辑层(如服务类)或应用层来处理。领域对象更像是一个数据容器,仅用于数据传递和存储。
充血模型:业务逻辑直接在实体内部实现,通过调用实体的方法来执行相关的业务操作。这样可以使业务逻辑更加内聚,提高代码的可读性和可维护性。
适用场景:
贫血模型:适合轻量级应用或团队内多人协作时,设计不容易变形。但在复杂业务中,梳理业务逻辑将变得非常困难,不利于项目后期的业务演进。
充血模型:适合业务复杂的应用场景。由于它将数据与业务能力绑定在一起,有助于更好的封装和保护领域内部的业务规则。但对业务的熟悉程度要求很高,需要在上手之初就设计好具体的模型实体和暴露的操作。
优缺点:
贫血模型:
优点:各层次之间松耦合,结构清晰,领域对象只是用作存放和传输的载体。
缺点:实体无法直接体现对应的业务能力,在复杂业务中梳理业务逻辑困难。
充血模型:
优点:对业务非常友好,有助于更好的封装和保护领域内部的业务规则。
缺点:对业务的熟悉程度要求高,需要设计好模型实体和暴露的操作。
综上所述,DDD中的充血模型和贫血模型在业务逻辑处理、适用场景以及优缺点等方面存在显著区别。选择使用哪种模型取决于具体的业务需求和开发团队的技术能力。
总的来说,充血模型强调领域对象的行为和状态,鼓励将业务逻辑封装在领域对象内部,使得对象自身具有丰富的行为和状态;而贫血模型则将更多的业务逻辑放在外部,领域对象主要作为数据的容器。在实际应用中,选择充血模型还是贫血模型需要根据具体的业务场景和需求来进行权衡和选择。

DDD的实现流程

领域驱动设计(DDD)是一种软件开发方法,旨在解决复杂领域中的设计和开发挑战。DDD强调对领域知识的建模,并将其反映在软件设计和实现中。以下是典型的DDD实现流程:

  1. 领域建模:
    首先,通过与业务专家和领域专家合作,深入了解业务领域,收集业务需求和规则。
    建立领域模型,包括实体、值对象、聚合根、领域服务等,用于表达业务概念和关系。
  2. 划分限界上下文:
    将整个领域划分为多个限界上下文(Bounded Context),每个限界上下文都有清晰的边界和语境,对特定的业务领域负责。
    每个限界上下文可以有自己的领域模型和语言,但要与其他上下文保持协调和一致性。
  3. 实现领域模型:
    使用面向对象编程或其他适合的技术实现领域模型,包括实体、值对象、聚合根、领域服务等。
    在实现过程中,应该尽可能地保持领域模型的纯净性和表达力,避免受到技术限制和外部因素的影响。
  4. 持续演化和迭代:
    随着对业务领域的理解不断深入和业务需求的变化,领域模型需要不断地演化和改进。
    通过持续的迭代和反馈,不断完善领域模型,使其更好地反映业务现实,并满足业务需求。
  5. 领域驱动架构:
    在系统架构设计中,采用符合领域驱动设计思想的架构模式,如充血模型、领域事件驱动架构(EDA)等,以支持领域模型的有效实现和演化。
  6. 持续集成和交付:
    将实现的领域模型集成到整个系统中,进行持续集成和交付,确保领域模型能够与其他部分协同工作,并满足系统整体的需求。
  7. 监控和反馈:
    在实际运行中,持续监控领域模型的表现和业务效果,并根据反馈及时调整和优化领域模型。
    总而言之,DDD的实现流程是一个不断理解业务、建模、实现、演化和优化的循环过程,需要密切与业务专家和技术团队合作,注重对业务领域的深入理解和持续学习。

实体(Entities)和值对象

在领域驱动设计(DDD)中,实体(Entities)和值对象(Value Objects)是两种常见的领域模型概念,用于表示领域中的不同类型的对象。

  1. 实体(Entities):
    实体是具有唯一标识的领域对象,通常代表系统中具有生命周期和状态的实际事物。
    实体具有唯一的标识符,通过标识符来区分不同的实体对象。
    实体通常具有丰富的行为和状态,可以在其生命周期内发生变化。
    实体对象的状态的改变可以引起系统的状态变化和业务流程的触发。
  2. 值对象(Value Objects):
    值对象是没有唯一标识的领域对象,通常代表系统中的一些简单的、不可变的值。
    值对象的相等性是通过其所有属性的值来确定的,而不是通过唯一标识符。
    值对象通常没有自己的生命周期和状态,它们的值一旦确定就不会改变。
    值对象通常用于描述一些概念性的属性或者数据结构,例如日期、金额、地址等。
    在实际应用中,实体和值对象的区分非常重要:
    对于具有生命周期和状态的事物,应该设计为实体,例如用户、订单、产品等。
    对于描述性质或者属性的概念,应该设计为值对象,例如日期、货币金额、地理位置等。
    正确地区分实体和值对象,有助于更清晰地理解和建模领域对象,提高系统的设计质量和可维护性。

领域事件

在领域驱动设计(DDD)中,领域事件(Domain Events)是指领域中发生的重要事件或者状态变化,它们通常表示领域中的一些关键业务发生了变化,或者某些重要的领域操作已经完成。
领域事件具有以下特点:

  1. 描述性:领域事件描述了领域中发生的具体事件或者状态变化,例如订单被创建、库存被更新、用户注册成功等。
  2. 异步性:领域事件通常是异步发生的,即事件的产生和处理是独立于业务操作的,可以通过消息队列或者事件总线来进行异步处理。
  3. 松耦合性:领域事件可以帮助实现领域模型之间的松耦合,因为它们可以作为领域边界的信号,让不同的领域模型之间通过事件进行通信和协作。
  4. 可溯源性:领域事件可以帮助实现系统的审计和溯源功能,因为它们记录了系统中重要的业务事件和操作,可以用于跟踪业务流程和历史记录。
    在实际应用中,领域事件通常与事件驱动架构(Event-Driven Architecture)结合使用,通过事件发布和订阅机制来实现领域模型之间的解耦和异步通信。领域事件的使用可以帮助实现敏捷开发和微服务架构中的事件驱动设计模式,提高系统的可扩展性和可维护性。

相关推荐

  1. DDD领域驱动设计(六)

    2024-06-07 03:06:04       38 阅读
  2. Golang 领域驱动设计DDD)最佳实践

    2024-06-07 03:06:04       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-07 03:06:04       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-07 03:06:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-07 03:06:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-07 03:06:04       18 阅读

热门阅读

  1. ASP.NET Core应用程序8:标签助手

    2024-06-07 03:06:04       9 阅读
  2. ASP.NET Core的开发效率利器HotReload(带例子)

    2024-06-07 03:06:04       14 阅读
  3. 通过SpringCloudGateway中的GlobalFilter实现鉴权过滤

    2024-06-07 03:06:04       11 阅读
  4. docker

    2024-06-07 03:06:04       9 阅读
  5. pymupdf提取pdf表格及表格数据合并

    2024-06-07 03:06:04       11 阅读
  6. vue html2canvas生成base64图片和图片高度

    2024-06-07 03:06:04       10 阅读
  7. 云计算的就业发展潜力怎么样?

    2024-06-07 03:06:04       12 阅读
  8. Go 文件压缩解压

    2024-06-07 03:06:04       9 阅读
  9. 2024-06-05 问AI: 介绍一下 SuperCLUE

    2024-06-07 03:06:04       9 阅读
  10. 海外金融牌照

    2024-06-07 03:06:04       9 阅读
  11. 我的创作纪念日

    2024-06-07 03:06:04       13 阅读