DDD入门学习系列之总篇

DDD整体介绍

DDD(Domain Drive Design 领域驱动设计)是由Eric Evans最新提出,是一种以领域为驱动的全新的软件设计和建模方法,其目的是通过对软件所涉及到的领域进行建模来应对系统规模过大时引起的软件复杂性问题。

为啥要DDD

软件分析和设计方法经历了三个阶段的演进:

第一阶段是单体架构时代:采用面向过程的设计方法,系统包括 UI 层和数据库两层,采用 C/S 架构模式,整个系统围绕数据库驱动设计和开发,新项目总是从设计数据库及其字段开始(ER模型、物理模型)。

第二阶段是集中式架构时代:采用面向对象的设计方法,系统包括 UI 层、业务逻辑层和数据库层,采用经典的三层架构,也有部分应用采用传统的 SOA 架构,这种架构易使服务变得臃肿,难于维护拓展,伸缩性能差。这个阶段系统分析、软件设计和开发大多是分阶段进行的。

第三阶段是分布式架构时代:由于微服务架构的流行,采用领域驱动设计方法,应用系统包括 UI 层、应用层、领域层和基础层。这个阶段融合了分析和设计阶段,通过建立领域模型,划分领域边界,做到领域模型既设计,代码与设计保持一致。
其中第一、二两个阶段是以数据库为中心的开发方式﹐将所有业务逻辑都放在了数据库﹐并结合系统的代码来保证业务逻辑的实现。
第三阶段以业务领域为中心,对业务领域进行建模,通过领域模型来驱动软件设计,并通过代码来表现领域模型。

  • 采用DDD的原因:
  1. 使领域专家和开发者一起工作,这样开发出的软件能准确的传达业务规则(软件就像如果领域专家是编码人员时所开发出来的一样)
  2. 可以帮助业务人员自我提高
  3. 关键在于对知识的集中,因为这样可以确保软件知识并不只是掌握在少数人的手中
  4. 在领域专家、开发者和软件本身之间不存在翻译,意思是大家都在使用相同的语言进行交流时,每人都能听懂他人所说。
  5. 设计就是代码,代码就是设计。设计是关于软件是如何工作的,最好的编码设计来源于多次试验,这得于敏捷的发现过程
  6. DDD同时提供了战略设计和战术设计两种方式。战略设计帮助我们理解哪些投入才是最重要的;哪些既有的软件资产是可以直接拿来使用的;哪些人应该被加入到团队中?战术设计则帮助我们创建DDD模型中的各个部件。
  • 采用DDD的业务价值:
  1. 你获得了一个非常有用的业务模型
  2. 你的业务得到了更准确的定义和理解
  3. 领域专家可以为软件设计作出贡献
  4. 更好的用户体验
  5. 清晰的模型边界
  6. 更好的企业架构
  7. 敏捷、迭代和持续建模
  8. 使用战略和战术新工具

如何DDD

战略设计

领域

从广义上讲,领域(Domain)即是一个组织所做的事情及其中所包含的一切。领域既可以表示整个业务系统,也可以表示其中的某个核心域或者支撑子域。
- 领域模型:关于某个特定业务领域的软件模型。通常,领域模型通过对象模型来实现,这些对象同时表达了数据和行为,并且表达了准确的业务含义。
- 领域专家:领域专家并不是一个职位,他可以是精通业务的任何人。他们可能了解更多的关于业务领域的背景知识,他们可能是软件产品的设计者,甚至可能是销售员。

通用语言

通用语言(Uniquitous Language)是团队共享的语言。领域专家和开发者使用相同的领域语言进行交流。事实上团队中每个人都使用相同的通用语言。不管你在团队中角色如何,只要你是团队中的一员你都将使用通用语言。

子域

一个领域被分为若干子域,子域包括:核心域、支撑子域、通用子域

  • 核心域
    核心域是整个业务领域的一部分,也是业务成功的主要促成因素。从战略层面上讲,企业应该在核心域上胜人一筹。我们应该给予核心域最高的优先级、最自身的领域专家和最优秀的开发团队。在实施DDD的过程中将主要关注核心域。
  • 支撑子域
    有时我们会创建或者购买某个限界上下文来支撑我们的业务。如果这样的上下文对应着业务的重要方面,但不是核心他就支撑子域。它专注与业务的某个方面
  • 通用子域
    如果一个子域被用于整个业务系统,那个这个子域就是通用子域
限界上下文

限界上下文是一个显示边界,领域模型存在于边界之内。在边界内通用语言中的所有属于和词组都有特定的含义,而模型需要准确的反映通用语言。

架构风格

DDD的一大好处就是它并不需要特定的架构。由于核心域位于限界上下文中,我们可以在整个系统使用多种架构风格。

  • 分层架构
  • 事件驱动架构
  • REST架构
  • 六边形架构
  • CQRS架构

战术设计

实体

表示那些具有声明周期并且会在其生命周期中发生改变的东西。实体具有唯一标识,只要唯一标识不同,就是两个不同的实体。

值对象

表示起描述性作用并且可以相互替换的概念,没有唯一标识,只是数据传输的载体,用描述性字段来实现。

领域服务

领域中一些概念不适合建模成对象,既不适合归类到实体或值对象,因为它们本质上是一些操作或者动作而不是实物。如:

  • 执行一个显著的业务操作过程。
  • 对领域对象进行转换。
  • 以多个领域对象作为输入进行计算,结果产生一个值对象。
    当一个方法不适合放在实体或者值对象上时,使用领域服务便是最佳的解决方法。领域服务是无状态的。
聚合及聚合根(Aggregate,Aggregate Root)

通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的、难以维护的对象关系网生成。聚合定义了一组具有具有内聚关系的相关对象的集合。
聚合根属于实体对象,它是领域对象中一个高度内聚的核心对象。(聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法)
​若一个聚合仅有一个实体,那这个实体就是聚合根;但要有多个实体,我们就要思考聚合内哪个对象有独立存在的意义且可以和外部领域直接进行交互。

领域事件

将领域中所发生的活动建模成一些列的离散事件,每个事件用领域对象来表示。通过领域事件的方式达到各个组件之间的数据一致性。领域事件的额外好处在于它可以记录发生在软件系统中所有的重要修改,这样可以很好地支持程序调试和商业智能化。另外,在CQRS架构的软件系统中,领域事件还用于写模型和读模型之间的数据同步。再进一步发展,事件驱动架构可以演变成事件源(Event Sourcing),即对聚合的获取并不是通过加载数据库中的瞬时状态,而是通过重放发生在聚合生命周期中的所有领域事件完成。

工厂

DDD中的工厂也是一种封装思想的体现。引入工厂的原因是:有时创建一个领域对象是一件相对比较 复杂的事情,而不是简单的new操作。工厂的作用是隐藏创建对象的细节。事实上大部分情况下,领域对象的创建都不会相对太复杂,故我们仅需使用简单的构造函数创建对象就可以。隐藏创建对象细节的好处是显而易见的,这样就可以不会让领域层的业务逻辑泄露到应用层,同时也减轻应用层负担,它只要简单调用领域工厂来创建出期望的对象就可以了。

资源库/仓储

资源仓储封装了基础设施来提供查询和持久化聚合操作。这样能够让我们始终关注在模型层面,把对象的存储和访问都委托给资源库来完成。它不是数据库的封装,而是领域层与基础设施之间的桥梁。DDD 关心的是领域内的模型,而不是数据库的操作。

参考资料:
《领域驱动设计:软件核心复杂性应对之道》
《实现领域驱动设计》

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值