DDD(Domain-Driven Design) 领域驱动设计
DDD(Domain-Driven Design) 领域驱动设计
1. DDD(Domain-Driven Design)是什么?
DDD是Eric Evans在2003年出版的《领域驱动设计:软件核心复杂性应对之道》(Domain-Driven Design: Tackling Complexity in the Heart
of Software)一书中提出的具有划时代意义的重要概念。
Domain-Driven Design 是指通过统一语言、业务抽象、领域划分和领域建模等一系列手段来控制软件复杂度的方法论。
DDD 的革命性在于领域驱动设计是面向对象分析的方法论,它可以利用面向对象的特性有效化解复杂性。
2. 数据驱动和领域驱动
2.1 数据驱动
目前的主流开发模式是数据驱动。有了需求先建数据库表,然后编写逻辑。
2.2 领域驱动
领域驱动设计关心的是业务中的领域划分(战略设计)和领域模型(战术设计),其开发过程不再以数据模型为起点,而是以领域模型为出发点。
领域模型对应的是业务实体,在程序中主要表现为类、聚合根和值对象,它更加关注业务语义的显性化表达,而不是数据的存储和数据之间的关系。这是“领域驱动设计”和“数据驱动设计”之间显著的区别。
3. 领域驱动设计优势
1. 统一语言
统一语言(Ubiquitous Language)的主要思想是让应用能和业务相
匹配,这是通过在业务与代码中的技术之间采用共同的语言达成的。
2. 面向对象
DDD的核心是领域模型,这一方法论可以通俗地理解为先找到业务中的领域模型,以领域模型为中心,驱动项目开发。领域模型的设计精髓在于面向对象分析、对事物的抽象能力,一个领域驱动架构师必然是一个面向对象分析的大师。
DDD鼓励我们接触到需求后第一步就是考虑领域模型,而不是将其切割成数据和行,然后用数据库实现数据,用服务实现行为,最后造成需求的首尾分离。DDD会让你首先考虑业务语言,而不是数据。DDD强调业务抽象和面向对象编程,而不是过程式业务逻辑实现。重点不同,导致编程世界观不同。
3. 业务语义显性化
统一语言使得我们的核心领域概念可以无损地在代码中呈现,从而提升代码的可理解性。
4. 分离业务逻辑和技术细节
代码复杂度是由业务复杂度和技术复杂度共同组成的。实践DDD还有一个好处,是让我们有机会分离核心业务逻辑和技术细节,让两个维度的复杂度有机会被解开和分治。
核心业务逻辑是整个应用的核心,最好只是简单Java类。也就是说,核心业务逻辑对技术细节没有任何依赖,依赖都是由外向内的,,即使有由内向外的依赖,也应该通过依赖倒置来反转依赖的方向。
4. 领域驱动设计核心概念
4.1 领域实体
面向对象编程的核心思想,也是DDD中寻找领域实体的核心思想。
领域实体其实就是对象。
4.2 聚合根
聚合根(Aggregate Root)是DDD中的一个概念,是一种更大范围的封装,会把一组有相同生命周期、在业务上不可分割的实体和值对象放在一起,只有根实体可以对外暴露引用,这也是一种内聚性的表现。
确定聚合边界要满足固定规则(Invariant),是指在数据变化时必须保持的一致性规则,具体规则如下:
- 根实体具有全局标识,最终负责检查规定规则
- 聚合内的实体(领域实体)具有本地标识,这些标识在Aggregate内部才是唯一的
- 外部对象不能引用除根Entity之外的任何内部对象
- 只有Aggregate的根Entity才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现。
- Aggegate内部的对象可以保持对其他Aggregate根的引用。
- Aggregate边界内的任何对象在修改时,整个Aggregate的所有固定规则都必须满足。
4.3 领域服务
有些领域中的动作是一些动词,看上去并不属于任何对象。它们代表了领域中的一个重要的行为。当这样的行为从领域中被识别出来时,推荐的实践方式是将它声明成一个服务。其作用仅仅是为领域提供相应的功能。
识别领域服务,主要看它是否满足以下3个特征。
- 服务执行的操作代表了一个领域概念,这个领域概念无法自然地隶属于一个实体或者值对象。
- 被执行的操作涉及领域中的其他对象。
- 操作是无状态的(无状态即没有保存数据)。
4.4 领域事件
领域事件(Domain Event)是在一个特定领域由一个用户动作触发的,是发生在过去的行为产生的事件,而这个事件是系统中的其他部分或者关联系统感兴趣的。
1.事件命名
事件是表示发生在过去的事情,所以在命名上推荐使用DomainName + 动词的过去式 + Event
,这样可以更准确地表达业务语义。
2.事件内容
事件内容在计算机术语中叫作payload
,有以下两种形式:
(1)自恰(Enrichment):就是在事件的payload中尽量多放数据,这样consumer不需要回查就能处理消息,也就是自恰地处理消息。
(2)回查(Query-Back):这种方式是只在payload放置id属性,然后consumer通过回调的形式获取更多数据。这种形式会加重系统的负载,可能会引起性能问题。
4.5 边界上下文
领域实体的意义是有上下文的。边界上下文(Bounded Context)的作用是限定模型的应用范围,在同一个上下文中,要保证模型在逻辑上统一,而不用考虑它是不是适用于边界之外的情况。
那么不同上下文之间的业务实体要如何实现交互呢?
就像关系数据库和对象之间需要ORM一样,不同上下文之间的实体也需要映射。
在DDD中,这种机制叫作上下文映射(Context Mapping),我们可以使用防腐层(Anti-Corruption)来完成映射的工作。
5 领域建模方法
5.1 用例分析法
用例分析法是进行领域建模中最简单可行的方式。步骤如下:
1. 获取用例描述
是一段格式化的需求文字描述。
2. 寻找概念类
寻找概念类就是对获取的用例描述进行语言分析,识别名词和名词短语,将其作为候选的概念类。
3. 添加关联
关联意味着两个模型之间存在语义联系,在用例中的表现通常为两个名词被动词连接起来。
4. 添加属性
我们需要区分概念类和属性(当然名词列表也会有无用的词语)。例如,对于上文抽取到的名词列表,“品名”是“商品”的属性,“iTouch”为无用的词语。
5. 模型精化
模型精化是可选的步骤,有时我们希望在领域模型中表达更多的信息,这时会利用一些新的手段来表达领域模型,包括泛化、组合和子域划分等。
四色建模法
四色建模法源于Peter Coad的Java Modeling In Color With UML一书,它是一种模型的分析和设计方法,要把所有模型分为4种类型,用4种颜色表示。
(1)业务关键时刻(Moment-Interval)
这种对象表示那些在某个时间点存在或者会存在一段时间。这样的对象往往表示了一次外界的请求,比如一次询价(Quotation)、一次下单(Order)或者一次租赁(Rental)。Moment-Interval是最重要的一类对象,是系统的价值所在,一般用粉红色来表示。这样的对象一般有一个起始时间和终止时间,以及一个唯一的标识号,用来唯一地标识这一次客户请求,比如OrderNo。注意,“业务关键时刻”是我给“Moment-Interval”起的中文名称,本来想直译为“时刻-时间段”,但感觉“时刻-时间段”不能体现出这种对象类型的重要性。
(2)角色(Role)
这种对象表示一种角色,往往由人或者物来承担,会有相应的责任和权利。一般,一个Moment-interval对象会关联多个Role。例如,一次下单涉及两个Role,分别是客户(Customer)和商品(Product)。这类对象是除Moment-interval对象之外最重要的一类对象,一般用黄色来表示。
(3)人-事-物(Party,Place or Thing)
这种对象往往表示一种客观存在的事物,例如人、组织、产品或者配件等。
(4)描述(Description)
这种对象一般是用于分类或者描述性的对象,它的属性一般是这一类事物都有的属性,一般用蓝色来表示。
资料
DDD(Domain-Driven Design) 领域驱动设计的更多相关文章
- DDD(Domain Driver Designer) 领域驱动设计简介
领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...
- DDD(Domain Driven Design) 架构设计
一.为什么要分层 分层架构是所有架构的鼻祖,分层的作用就是隔离,不过,我们有时候有个误解,就是把层和程序集对应起来,就比如简单三层架构中,在你的解决方案中,一般会有三个程序集项目:XXUI.dll.X ...
- DDD学习笔录——简介领域驱动设计的实践与原则
DDD在存在许多DDD模式的同时,也有大量实践和指导原则,这些都是DDD思想体系成功的关键. 1.专注于核心领域 DDD强调的是在核心子域付出最多努力的需要.核心子域是你的产品会成功还是会失败的差异化 ...
- csharp: Domain-Driven Design(领域驱动设计)
http://dddsample.sourceforge.net/ https://github.com/citerus/dddsample-core http://dddsamplenet.code ...
- (翻译)领域驱动设计实现-Implementing Domain Driven Design
简介 Implementing Domain Driven Design 领域驱动设计实现 A practical guide for implementing the Domain Driven D ...
- Java开发架构篇《初识领域驱动设计DDD落地》
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 DDD(Domain-Driven Design 领域驱动设计)是由Eric Eva ...
- 领域驱动设计(DDD:Domain-Driven Design)
领域驱动设计(DDD:Domain-Driven Design) Eric Evans的"Domain-Driven Design领域驱动设计"简称DDD,Evans DDD是一套 ...
- 领域驱动设计(DDD:Domain-Driven Design) 介绍
Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD ...
- 领域驱动设计(DDD:Domain-Driven Design) 转摘自:http://www.jdon.com/ddd.html
Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD ...
随机推荐
- 前端(react)上传到阿里云OSS存储 实例
需求背景 由于现有的后台管理系统,上传的视频越来越大,加上上传视频较慢,后端小哥提出直接从前端上传视频或者其他文件到阿里云OSS存储. 阿里云OSS 阿里云OSS文档介绍,这里不做过多赘述 安装 原本 ...
- Spring Boot 自定义Starter 可能引发的问题(Error)
如果你的项目出现: Consider defining a bean of type 'com.wy.helloworld_spring_boot_starter.PersonService' in ...
- eclipse中的项目如何打成war包
war包即Web归档文件,将Web项目打成war包可以直接拷贝到Web服务器发布目录(例如Tomcat服务器webapps目录 ),当Tomcat启动后该压缩文件自动解压,war包方便了web工程的发 ...
- 嵌套OOPS导致系统卡死 每个CPU都上报softlockup的问题
问题现象:在ARM服务器上,构造oops异常,本应该产生panic,进入dump流程,并且系统重启,但是系统并未重启,而是出现了卡死,在串口会隔一段时间就循环打印调用栈信息.如下所示 linux-fA ...
- Java中对文件的处理01-递归删除
package com.ricoh.rapp.ezcx.admintoolweb.util; import java.io.BufferedInputStream; import java.io.Bu ...
- phpmyadmin 4.8.1 文件包含漏
一. 启动环境 1.双击运行桌面phpstudy.exe软件 2.点击启动按钮,启动服务器环境 二.代码审计 1.双击启动桌面Seay源代码审计系统软件 3.点击新建项目按钮,弹出对画框中选择(C:\ ...
- IIS短文件猜解
1.IIS短文件漏洞 Microsoft IIS 短文件/文件夹名称信息泄漏最开始由Vulnerability Research Team(漏洞研究团队)的Soroush Dalili在2010年8月 ...
- ISR、OSR、AR 是什么?
ISR:In-Sync Replicas 副本同步队列 OSR:Out-of-Sync Replicas AR:Assigned Replicas 所有副本 ISR是由leader维护,followe ...
- 说出几条 Java 中方法重载的最佳实践?
下面有几条可以遵循的方法重载的最佳实践来避免造成自动装箱的混乱. a)不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参 数. b)不要重载参数数量一致,而只是参数顺序 ...
- Flask 简单使用,这一篇就够了!
#Flask 安装依赖包及作用 - jinja2 模板语言 (flask依赖包) - markupsafe 防止css攻击 (flask依赖包) - werkzeug --wkz 类似于django中 ...