领域驱动设计-领域建模

news2024/11/23 12:34:05

领域建模

领域建模是针对问题空间的战术求解的过程:观察真实世界的业务需求,对业务知识进行提炼和转换,排除技术因素对建模产生的影响,一切围绕着业务需求而来。同时满足未来的需求变更与产品维护

快速建模法:名次动词法

建模过程

  1. 名词建模
    1. 识别业务流程(用例)中的名词
  2. 动词建模
    1. 识别动词,判断对应的行为是否产生了过程数据(补充手段,看是否产生了影响管理、法律或财务的过程数据,如果缺少它的记录,就会影响到商业的运营管理、造成经济损失或引起法律纠纷)
  3. 归纳抽象
  4. 确定关系
    1. 确定领域概念之间的关系

名词建模

只要名词属于领域概念,符合统一语言的要求,就快速将他提取出来,放到领域分析模型中

动词建模

讲识别出来的动词当作一个领域行为,然后看他是否产生了影响管理、法律或财务的过程数据。

  1. 驱动出隐藏的关键概念:针对动词代表的领域行为,是否需要记录过程数据
  2. 验证挖掘出来的业务概念是否真的属于领域分析建模的核心概念:如果缺少了过程数据,是否影响运营管理、引起法律纠纷或造成经济损失

归纳抽象

为了提高模型的质量,可对已有领域概念进行归纳抽象,主要是针对由那些定语修饰的领域概念。如配送地址、家庭地址、已付款金额、冻结资金等。需要分辨他们是类型的差异还是值的差异,如果是值的差异,类型相同,应归为一个领域概念。

  • 比如收获地址和家庭地址表达了不同的值,但实际上都是地址Address类型
  • 订单状态和商品状态修饰的都是状态,但实际上代表完全不同的值(类型),两个概念不能合并

注意:在分析阶段,如果分不清楚一个模型应该保留还是删除时,应优先考虑保留,待到领域姜末设计时在进行判断

确定关系

如果某个类型拥有多种相似的关联,可以为这些关联对象定义一个新的类型。也就是说如果发现用一个领域概念来描述关系更为合理,就可以将该关系建模为一个领域概念。比如:读者和作平之间存在关联关系,表达了一种收藏的概念,故可以提炼出收藏的概念

建模书籍:《分析建模:可复用的对象模型》,《彩色UML建模》


领域模型设计要素

  1. 实体:谓语描述的主体
  2. 值对象:为主体对象的属性
  3. 领域事件:封装了主体的状态
  4. 领域服务

1、实体

巴门尼德认为实体是不同变化状态的主体:主体的状态在相当长一段时间内会持续的变化,因此需要一个身份标识来标记。一个实体应具备3个要素:

  1. 身份标识
  2. 属性
  3. 领域行为

身份标识

身份标识是实体对象的必要标识,在领域驱动设计中,没有身份标识的领域对象就不是实体。身份标识的主要目的是管理实体的生命周期

属性

实体的属性用来说明主体的静态特征,可分为:

  • 原子属性:不可再分。【基本类型】
  • 组合属性

如何定义属性是原子属性和组合属性?

  • 划分标准:该属性是否存在约束规则、组合因子或属于自己的领域行为
  • 约束规则:即为业务规则
  • 组合因子:是否不可再分。比如重量、体积,需要与计数单位共同组合,如果只有值而无单位,就会因为单位不同导致计算错误
  • 领域行为:每个抽象层只专注于做自己的事情,各司其职,这样实体类就能分配职责

领域行为

领域行为:可以更好的说明其作为主体的动态特征

  1. 变更状态的领域行为:应该让变更状态的方法名满足业务含义
  2. 自给自足的领域行为:意味着实体对象只操作了自己的属性
  3. 互为协作的领域行为:通过方法参数传入

实体拥有的变更状态的领域行为,修改的只是对象的内存状态,与持久化无关

2、值对象

值对象是不可变的,不需要分配标识。实体与值对象的本质区别在于是否拥有唯一的身份标识

值对象和实体的区别

  • 业务对它相等的判断是:依据值还是依据身份标识
  • 确定属性值是否会发生变化:如果变化了,是产生一个完全不同的对象,还是维持相同的身份标识。前者是值对象,后者是实体
  • 生命周期的管理:值对象没有生命周期的管理

不变性

领域驱动设计建议尽量将值对象设计为不变类,因为一个不变的类是线程安全的。如果既要保证对象的不变性,又要满足更新状态的需求,就需要用一个保存了新状态的实例来替换原有的不可变对象

值对象的优势

  1. 内建类型无法展示领域概念,比如String 和 Name
  2. 内建类型无法封装领域逻辑
  3. 内建类型缺乏验证能力

3、聚合

类的关系

  1. 泛化: 子类继承父类
  2. 关联:代表整体的对象包含了代表部分的对象,即为组合关系
    1. 合成:体现了强烈的所有权的特征,即组合关系的两个对象属于同一个生命周期。比如学校和教室
    2. 聚合:没有所有权特征,不会约束它们的生命周期。比如教室和学生
  3. 依赖:一个类使用了另一个类的信息或服务

引入边界:聚合

当规模越来越大时,类之间的关系变得错综复杂,对象的层次变得越来越深,类之间的关系难以梳理和控制。因此需要引入边界来降低和限制领域类之间的关系,每个边界都有一个主对象作为外交发言人,总体负责与外部的协作。

  • 就好像公司员工多了之后,会分部门,部门下会分团队,便于管理

引入这种关系后,就可以只保留主对象之间的关系。这种层次的边界称为聚合,边界内的主对象称为聚合根。聚合在限界上下文与类的粒度之间形成了中间粒度的封装层次

聚合的特征

  • 聚合是包含了实体和值对象的一个边界
  • 聚合内包含的实体和值对象形成一棵树,只有实体才能作为这颗树的根:因为聚合需要通过资源库管理生命周期,要管理生命周期,就需要通过身份标识对其进行跟踪
  • 外部对象只允许持有聚合根的引用
  • 聚合内部需要保证事务的一致性
  • 由聚合根统一对外提供履行该领域概念职责的行为方法,实现内部各个对象之间的协作

聚合的设计原则

**当聚合边界存在模糊时,独立性对聚合边界的影响要高于完整性。**完整性将聚合视为一个高内聚的整体,独立性影响了聚合的粒度,不变量时对动态关系的业务约束,一致性体现了聚合数据操作的不可分割

  • 完整性
    • 对内、对外有一致的生命周期
  • 独立性
    • 需要看待合并实体是否会被调用者单独使用,比如汽车和发动机。汽车没有发动机不完整,但是发动机可以单独使用
    • 当聚合边界存在模糊时,独立性对聚合边界的影响要高于完整性
  • 不变量
    • 聚合内部的恒定关系,可以理解为固定规则
  • 一致性:事务的一致性
    • 原子性:聚合不可再分的领域概念
    • 一致性:聚合边界内最重要的不变量就是一致性约束
    • 隔离性:通过唯一的身份标识进行聚合关联
    • 持久性:一个聚合只有一个资源库,由资源库保证聚合整体的持久化

最高原则

只有聚合根才是访问聚合边界的唯一入口,聚合外部的对象不能引用除根实体之外的任何内部对象。聚合之间通过身份标识进行引用

4、聚合生命周期的管理

生命周期经历的各种状态取决于存储介质,内存与硬盘,分别对应对象的实例化与数据的持久化。如果不是因为计算机无法做到永不宕机且内存资源便宜,那么是可以不进行持久到外部存储设备中。

在领域模型的设计要素中,由聚合根实体的构造函数或者工厂负责聚合的创建,若要修改聚合的状态,需要在内存中先进行状态的变更,然后通过持久化确保聚合对象与数据记录的一致

工厂

**工厂封装了聚合对象的创建逻辑。**许多面向对象与药支持类通过构造函数创建自己,对象自己创建自己,就好像扯着自己的头发离开地球表面,不合情理。

  • 由被依赖聚合担任工厂
  • 引入专门的聚合工厂
  • 聚合自身担任工厂
  • 消息契约模型或装配器担任工厂
  • 使用构建者组装聚合

资源库

资源库是对数据访问的一种业务抽象,分离了聚合的领域行为和持久化行为,保证了领域模型对象的业务纯粹性。

一个聚合一个资源库,如果要访问聚合内的非根实体,需要通过聚合访问。在资源库获得整个聚合后,将根实体作为入口,在内存中访问封装在聚合边界内的非根实体对象

  1. 资源库和数据访问对象(DAO)的区别?
    • 数据访问对象在访问数据时,无聚合的概念,可以针对领域层的任何模型对象
  2. 如何设计资源库接口?
    1. 一派认为以通用性换取接口的可扩展,但却牺牲了接口方法的可读性
    2. 一派以封装获得接口的可读性,却因为方法过于具体导致接口膨胀与不稳定

可以一边为资源库定义常见的个性化查询方法,一边保留对查询条件的支持。因为一旦资源库提供了通用的查询接口,就会将组装查询条件的代码混入应用层,违背了保持应用层轻薄的原则

5、领域服务

聚合的已知数据不一定满足完整的领域需求,为了保证聚合的自治性,需要将不足的部分作为方法的参数传入。但两个聚合之间的协作应该由谁负责发起呢?——由领域服务负责

运用场景

  1. 当针对领域行为建模时,优先考虑使用值对象和实体来封装领域行为。如果领域行为的变化方向没有拥有数据的类保持一致,就应分离变与不变,将这一变化的领域行为从所属的聚合中剥离出来,形成领域服务
  2. 当有两个聚合需要进行协作时,该由领域服务负责
  3. 当业务需要调用其他服务时,也应该由领域服务负责,不应该在聚合内部引入对南向网关端口的依赖

归纳为:

  1. 与状态无关的领域行为
  2. 变化方向与聚合不一致的领域行为
  3. 聚合之间协作的领域行为
  4. 聚合和端口之间协作的领域行为

6、领域事件

特征

  1. 领域事件代表了领域概念
  2. 领域事件是已经发生的事实
  3. 领域事件是不可变的领域对象
  4. 领域事件会基于某个条件而触发

定义

  1. 事件ID:通过ID唯一标识事件,进行管理
  2. 事件发生时间

领域设计建模

实体、值对象与领域事件共同构成了描述真实世界业务问题的基本要素;聚合从设计角度为实体与值对象圈定了概念边界,并映入了工厂和资源库的设计模式,用于管理聚合的生命周期;领域服务作为聚合的补充,专注于领域行为的表达,负责协调聚合之间以及聚合与端口之间的协作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qy7CBxRE-1669707561663)(images/Z0bukJd4bYhhjqw6O-QoF60UclBc8ae9cn3TZJi8c3k.png)]

  • 远程服务:若为当前限界上下文的远程服务,负责响应角色的服务请求
  • 应用服务:提供具有服务价值的服务接口,完成消息契约对象与领域模型对象的转换,调用货编排领域服务
  • 领域服务:提供聚合无法完成的业务功能,协调多个聚合以及聚合与端口之间的协作。封装领域逻辑,以避免其泄漏到应用层
  • 聚合:作为信息的持有者,履行自给自足的领域行为
  • 工厂:封装复杂货可能变化的创建聚合的逻辑
  • 端口:作为访问外部资源的抽象
  • 适配器:端口的实现,提供访问外部资源的具体技术实现,并通过依赖注入设置到领域服务或应用服务中

设计聚合

  1. 理顺对象图:辨别实体还是值对象
  2. 分解关系薄弱处:以关系强弱为界,以聚合边界为刀,逐一分解
  3. 调整聚合边界

分解关系

泛化关系的处理

  • 整体视角:调用者不关心特化的子类之间的差异
  • 独立视角:调用者只关注具体的特化子类,此时应以特化的子类作为独立的聚合根

如果一个继承体系的子类存在不同于父类和其他子类的特定属性,说明该子类具有了领域概念的独立性。

如果是合成关系,也属于一个聚合

服务驱动设计

在这里插入图片描述

  1. 分解任务:根据职责的层次对业务服务进行任务分解,直到分解为原子任务
    1. 同一层次的任务必须位于同一个抽象层次
  2. 分配职责:为角色构造分配不同层次的职责

分解任务

  1. 把基本流程以动词短语形式列出,作为基础任务
  2. 以归纳法将具有相同目标的基础任务由上而下归纳为组合任务
    1. 比如验证订单有效性和验证库存有效性具有共同的目标,就是验证订单可以归纳为一个组合任务
  3. 再以分解法判断基础任务是否是原子任务,如果不是,就自上而下进行拆分

分配职责

  1. 远程服务:匹配业务服务
  2. 应用服务:匹配业务服务。自身并不包含任务领域逻辑,仅负责协调领域模型对象,通过它们的领域能力组合完成一个完整的应用目标,完成对领域服务和聚合的协调
  3. 领域服务:匹配组合任务,领域服务的主要目的就是控制多个聚合与端口之间的协作
  4. 聚合:匹配原子任务
  5. 端口:匹配原子任务,抽象对外部资源的访问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通信原理技术复习重点知识

1.感知控制层通信的目的和特点: 目的:将各种传感设备(数据采集设备以及相关的控制设备)所感知的信息在较短的通信距离内传送到信息汇聚系统,并由该系统传送到网络传输层 特点:传输距离近,传输方…

使用 SAP WebIDE 将 SAP UI5 应用部署到 ABAP 系统时遇到的关于传输请求的错误

有朋友遇到一个在 webide 里部署 SAP UI5 应用到 ABAP Repository 里时出错的问题: 错误消息: Failed to get transports for the selected package. Request POST /webidedispatcher/destinations/LND500/sap/bc/adt/cts/transportchecks failed: Forbi…

【数学】仿射变换(续1)

在 这篇文章 中我介绍了椭圆中的圆幂定理。其中,椭圆中的“相交弦定理”为 PA⋅PBPC⋅PDrAB2rCD2\frac{PA\cdot PB}{PC \cdot PD}\frac{r_{AB}^2}{r_{CD}^2}PC⋅PDPA⋅PB​rCD2​rAB2​​ 本来以为它是从来见不到的东西 然而 请看此题: 以下给出两种常…

传奇登录器打不开的四种原因

最近很多传奇玩家或者GM都遇到了传奇登陆器打不开,没反应,提示无法访问指定设备等问题,导致很多游戏没有办法玩,让玩家心情沮丧,作为GM,那么就更伤心了,很多玩家进不来游戏,开服数千…

Vue3框架中路由的使用和局部刷新的功能(第十一课)

使用vue-router的步骤:p第一步:创建路由需要映射的组件(打算显示的页面);p第二步:通过createRouter创建路由对象,并且传入routes和history模式;配置路由映射: 组件和路径映射关系的routes数组&a…

linux杀毒软件clamav安装

clamav 简介 ClamAV is an open source (GPLv2) anti-virus toolkit, designed especially for e-mail scanning on mail gateways. It provides a number of utilities including a flexible and scalable multi-threaded daemon, a command line scanner and advanced tool …

Git的基本使用

Git 1.Git基础知识 1.1Git简介 更新的历史保存在Gitee中不会丢失的。 1.简介:Git是一个分布式版本管理系统,是为了更好地管理Linux内核开发而创立的。 Git可以在任何时间点,把文档的状态作为更新记录保存起来。因此可以把编辑过的文档复…

AI强势入场,成就史上最快足球

众所周知,卡塔尔是全球最富裕的国度之一,是世界第一大液化天然气生成和出口国。丰富的石油资源,几乎让每一名原住民从出生之日起就实现财务自由,人均GDP高达6万多美元,钞能力毋庸置疑。 2022年世界杯正是在这片富饶的土…

图论 - 拓扑排序

有向图的拓扑序列 给定一个 nnn 个点 mmm 条边的有向图,点的编号是 111 到 nnn,图中可能存在重边和自环。 请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。 若一个由图中所有点构成的序列 AAA 满足&#xf…

调试-一些奇怪的现象-以及const的作用

今天给大家看一些奇怪的例子&#xff0c;我们用调试来看看这到底是什么情况&#xff0c;本次选取环境为vs2019 话不多说&#xff0c;我们直接来看例子 #include <stdio.h>int main() {int i 0;int arr[10] { 0 };for (i 0; i < 12; i){arr[i] 0;printf("he…

压缩包加密、解密

压缩包文件大家都经常使用&#xff0c;经常用来压缩文件之后再转发给别人&#xff0c;网上下载的软件&#xff0c;有时候也是压缩包形式下载下来&#xff0c;解压之后才是软件。相信大家一定也遇到过加密的压缩包文件。今天和大家分享如何加密压缩包&#xff0c;以及如何解密压…

114.(leaflet篇)leaflet空间判断-点与圆的空间关系

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>

【SpringBoot】对于yaml的详细学习和三种属性赋值的实战详解

一.yaml详细讲解 1.1 什么是yaml&#xff1f; YAML是一种数据序列化语言&#xff0c;通常用于编写配置文件。业界对YAML有不同的看法。有些人会说YAML代表另一种标记语言。其他人认为“YAML不是标记语言”&#xff08;“YAML并非标记语言”&#xff09;。“YAML”只是这句话的…

CentOS中使用Docker部署带postgis的postgresql

场景 CentOS中使用Docker来部署Postgresql&#xff1a; CentOS中使用Docker来部署Postgresql_霸道流氓气质的博客-CSDN博客 上面安装的postgresql还需自行安装postgis插件&#xff0c;是否可以直接安装带postgis插件的postgresql。 注&#xff1a; 博客&#xff1a;https:…

RKMEDIA使用简介

瑞芯微&#xff08;rockchip&#xff09;芯片现在嵌入式行业使用的逐渐多了&#xff0c;本栏主要介绍rv1126/rv1109上的媒体框架 rkmedia的使用以及常遇到的问题。 希望可以给各位使用rkmedia的小伙伴一些帮助&#xff0c;同时也是自己工作的记录。 rkmedia的手册在sdk目录下/…

windows10系统安装nvm切换电脑node版本

介绍 nvm 是 node version manager&#xff08;node 版本管理工具&#xff09;的缩写&#xff0c;是一个命令行工具&#xff0c;用于管理和切换到不同版本的 node.js。 不同的项目可能需要不同版本的 node.js 和 npm&#xff08;node 包管理器&#xff09;&#xff0c;例如&a…

(二)devops持续集成开发——jenkins的权限管理配置

前言 jenkins作为目前主流的devops工具&#xff0c;受到了广大开发用户的追捧。由于其丰富的插件库&#xff0c;其可插拔的功能使得其功能和生态都十分强大。本节内容是关于jenkins的权限管理组件Role-based Authorization Strategy的安装及使用。 正文 下载安装Role-based A…

极验--一键通过模式逆向分析

内容仅供参考学习 目标 网址&#xff1a;https://www.geetest.com/demo/fullpage.html 这次只是简单的进行一次分析&#xff0c;如果有需要可以直接看最后 流程分析 打开调试工具&#xff0c;刷新一下页面&#xff0c;获取初始的交互信息&#xff1a; 先看第一个&#x…

3.RabbitMQ工作模式介绍

3.RabbitMQ工作模式介绍.md 文章目录3.RabbitMQ工作模式介绍.md1.简单模式1.1总结2.Work Queues 工作队列模式2.1 模式说明2.2 代码编写2.3 总结3.Pub/Sub 订阅模式3.1 模式说明3.2 使用场景3.3 代码实现3.4 总结&#xff1a;4.Routing 路由模式4.1 模式说明4.2 代码编写4.3 总…

CAS:304014-13-9,淬灭剂QSY21 NHS ,QSY 21NHS 试剂供应

一&#xff1a;产品描述 1、名称 QSY 21NHS 淬灭剂QSY21 NHS 淬灭剂QSY21 NHS ester 2、CAS编号&#xff1a;304014-13-9 3、分子式&#xff1a;C45H39ClN4O7S 4、分子量&#xff1a;815.34 5、外观&#xff1a; 紫色固体 &#xff08;具体由其分子量大小决定外观&am…