DDD(3)-领域驱动设计之如何建模

前言

上一篇:从领域驱动到模型驱动中我们讨论到,领域驱动设计的核心思想是保持业务-模型-代码的一致性,模型作为沟通业务和代码的工具,至关重要,今天这篇文章就来讨论DDD中建模的一些思考和方法。

什么是建模

虽然看到这篇文章的读者都是IT从业人员,大家都知道建模是怎么回事,但我还是想先对建模这件事讨论几句,我理解的建模,是对业务中数据流的合适描述。业务是公司的经营活动,但是在软件工程范畴中,当业务人员找到开发说要开发个系统来管理业务的时候,其本质是需要一个能管理业务中数据的系统。因为软件系统唯一能处理的只有数据,它不可能做到把货物从A运到B类似的事情,但它可以通过把“货物从A运到B”这件事情通过数据的方式传递给合适人去完成。因此,我们构建软件系统时唯一关注的是如何处理业务中的数据。业务中的数据具有历史性,即其会随着业务的流转而变化,衍生出新的数据。将业务全周期中的所有数据视为一个集合,不同的业务阶段、业务操作、业务视角都是关注集合中部分数据并筛选出来形成一个子集。例如电商场景中,一个完整的订单流程包含用户浏览商品、下单、付款、物流等阶段,包含商品名称、用户地址、付款渠道、物流明细等数据。但在不同的业务阶段,不同的业务角色只关注部分数据,但因为各参与方都使用同一套系统(同一套数据),因此系统还要关注模型间数据的流转路径。将数据集合进行划分,并描述其变化路径,这就是建模。

什么算好的建模

模型包含数据和行为。模型本质上是一个集合,是为了最大限度满足使用方信息完备要求并且使得系统管理代价最小的平衡结果。这里说得系统管理代价,实际上是指数据规模、信息密度超出人脑处理信息上下文的容量后带来的复杂度急剧上升,从而无法做出有效、正确决策,使得系统和业务的一致性越来越低,使软件系统在错误的道路上越走越远。因此建模的评判标准有三个:1、和业务保持一致;2、信息完备;3、管理代价最小。
“和业务保持一致”:
这里就是DDD中提倡的“共同语言”,创建的模型应该能和业务中的概念术语一一对应,不能自己创造、篡改、臆想出一个模型,应该是业务流程中确实存在、需要的数据子集。数据的流转应该符合业务实际中的数据变化实际,而不能为了技术、性能、方便等理由而强行创建出一条数据流。
“信息完备”是指应该从业务流程出发,将上下文需要的数据都在模型中体现。如果某个数据在节点3处使用,而它是在节点1出产生的,那么它就应该沿着节点1-节点2-节点3的路径流转,而不是在节点3处再去节点1中获取。
“管理代价最小”主要指的是系统复杂度要最小,复杂度的度量有两个指标:模型数量和模型关系,且模型关系对复杂度的影响远大于数量。这里说得复杂度仍然是描述开发人员对系统的理解、掌握、改造时要处理的信息大小。为什么说关系对复杂度的影响远大于数量呢?
一本新华字典的体量远大于一本红楼梦小说,但理解红楼梦的复杂度远大于新华字典。因为字典中收录的汉字都是独立的,前后并无强烈关联。但红楼梦中包含的人物、故事纷纭复杂,想要读懂甚至修改红楼梦需要大师级的文学素养。因此建模时我们应该着力避免模型间的关系,必要时可以用模型的数量来规避关系。

建模方法

由于DDD追求建模和业务的一致性,且愿意使用模型的数量来置换关系以追求系统的复杂度降低,DDD中常采用的建模方法是CQRS(Command Query Responsibility Segregation,命令查询职责分离)和命令-事件模型,。CQRS将系统的功能分为两类:写操作和读查询,每个写操作视为一个命令,是真正的业务流程,只针对写操作建模。而读请求不会对系统造成更改,可以直接从数据层取数据组装返回。大部分系统属于写少读多,运用CQRS的方式会大大降低建模难度。
命令-事件模型将系统中的写操作分类两部分:命令、事件,命令由外部触发,其携带了上下文数据,命令通过执行对系统的状态(数据)产生了变更,由此产生了事件,该事件携带了一些数据,可能被系统中某些部分关注,从而做出反应,这些反应通常也会使用执行命令的方式完成,由此循环往复,把系统中的所有写操作使用命令-事件模型描述清楚。
例如,用户选择商品后点击下单,对于系统来说,用户触发了一个命令,该命令包含了用户和商品等上下文数据,系统需要执行该命令。通过某个命令执行器,将“创建订单”命令执行完毕后,系统中将会保存一份订单数据,还需要广播一个事件“订单已创建”,其将包含已创建订单的关键信息。用户积分管理业务关注“是否有订单创建”这件事,通过合适的方式监听到“订单已创建”事件,将自己要进行的业务操作,也封装成一个命令,通过专有的命令执行器处理自己的业务。
CQRS

为何命令-事件模型适合DDD?

命令-事件模型只是一种建模方法,其可以脱离DDD使用,但因为其具有的几个特点,使得其非常适合应用在DDD中。
1、命令-事件模型只针对写操作建模,符合CQRS思想。
2、命令-事件的万能句式是:xxx操作触发了yyy事件,发生yyy事件时做zzz操作。使用这样的句式能将业务流程、内里变化描述得非常清晰,而且只需要命令、事件两类模型即可完成建模,意味着模型和业务保持一致非常容易。
3、由于建模结果容易理解,且具有很强的业务表达能力,意味着使用代码描述模型将会非常容易,因此更能保证代码和模型的一致性。
4、命令-事件天然具有对应关系,而事件到命令可通过命令总线方式隔离、解耦,使得系统中模型间关系减少,大大降低了系统复杂度。

总结

本篇主要分析DDD中对建模的一些要求,建模首先要保证和业务的一致性,齐次通过减少关系来降低结果复杂度。CQRS+命令-事件模型是目前DDD中的操作性强、适应范围广的,符合DDD核心要求的可落地建模方法。这里推荐一个B站视频:Java8 到 .NET8 - 掌握这个模型你就能设计一切,详细介绍了如何使用命令-事件模型进行建模的细节。

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

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

相关文章

基于SSM的高考志愿选择辅助系统

基于SSM的高考志愿选择辅助系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台 前台首页 院校展示 后台 后台首页 学校管理 摘要 随着高考制度的不断完…

【Drone】drone编译web端 防墙策略 | 如何在被墙的状态drone顺利编译npm

一、drone编译防墙版本 1、web端drone kind: pipeline type: docker name: ui steps:- name: build_projectimage: node:20-slim depends_on: [clone]volumes:- name: node_modulespath: /drone/src/node_modulescommands:- pwd- du -sh *- npm config set registry https://…

测试——Selenium

内容大纲: 什么是自动化测试 什么是Selenium Selenium工作原理 Selenium环境搭建 Selenium API 目录 1. 什么是自动化测试 2. 什么是Selenium 3. Selenium工作原理 4. Selenium环境搭建(java) 5. Selenium API 5.1 定位元素 5.1.1 CSS选择器定位元素 5.1.2 XPath定位元…

k8s中部署nacos

1 部署nfs # 在k8s的主节点上执行 mkdir -p /appdata/download cd /appdata/download git clone https://github.com/nacos-group/nacos-k8s.git 将nacos部署到middleware的命名空间中 kubectl create namespace middleware cd /appdata/download/nacos-k8s # 创建角色 kub…

VScode连接虚拟机运行Python文件的方法

声明:本文使用Linux发行版本为rocky_9.4 目录 1. 在rocky_9.4最小安装的系统中,默认是没有tar工具的,因此,要先下载tar工具 2. 在安装好的vscode中下载ssh远程插件工具 3. 然后连接虚拟机 4. 查看python是否已经安装 5. 下载…

【状态估计】偏差,匹配和外点

我们都知道:对于状态的估计可能是有偏差的,特别是在运动模型或观测模型是非线性的情况下。在简单的立体相机的例子中,我们看到MAP方法相比于全贝叶斯方法来说是有偏差的。同时,我们也看到批量ML方法对于真实值来说也是有偏差的&am…

openEuler操作系统下Oracle 19c 从19.3补丁更新到19.17

Oracle 19c 从补丁19.3更新到19.17的过程涉及到多个步骤,包括备份、下载补丁、替换OPatch、验证清单信息、冲突检测、空间检测、应用补丁等。以下是一个概括性的流程,但请注意,具体步骤可能会根据实际的Oracle环境、补丁内容和Oracle的官方指…

【接口自动化_07课_Pytest+Excel+Allure完整框架集成_下】

目标:优化框架场景 1. 生成对应的接口关联【重点】 2. 优化URL基础路径封装【理解】 3. 利用PySQL操作数据库应用【理解】--- 怎么用python连接数据库、mysql 4. 通过数据库进行数据库断言【重点】 5. 通过数据库进行关联操作【重点】 一、接口关联&#xff1a…

【QAC】分布式部署下其他机器如何连接RLM

1、 文档目标 解决分布式部署下其他机器如何连接RLMLicense管理器。 2、 问题场景 分布式部署下QAC要在其他机器上单独运行扫描,必须先连接RLMLicense管理器,如何连接? 3、软硬件环境 1、软件版本:HelixQAC23.04 2、机器环境…

【算法/训练】:前缀和差分

🚀 前言: 前面我们已经通过 【算法/学习】前缀和&&差分-CSDN博客 学习了前缀和&&差分的效相关知识,现在我们开始进行相关题目的练习吧 1. 校门外的树 思路:给[0, n]的数组都标记为1,然后输出m行范围…

基于 PyTorch 的模型瘦身三部曲:量化、剪枝和蒸馏,让模型更短小精悍!

基于 PyTorch 的模型量化、剪枝和蒸馏 1. 模型量化1.1 原理介绍1.2 PyTorch 实现 2. 模型剪枝2.1 原理介绍2.2 PyTorch 实现 3. 模型蒸馏3.1 原理介绍3.2 PyTorch 实现 参考文献 1. 模型量化 1.1 原理介绍 模型量化是将模型参数从高精度(通常是 float32&#xff0…

Elasticsearch:Retrievers 介绍 - Python Jupyter notebook

在今天的文章里,我是继上一篇文章 “Elasticsearch:介绍 retrievers - 搜索一切事物” 来使用一个可以在本地设置的 Elasticsearch 集群来展示 Retrievers 的使用。在本篇文章中,你将学到如下的内容: 从 Kaggle 下载 IMDB 数据集…

Linux云计算 |【第一阶段】SERVICES-DAY5

主要内容: 源码编译安装、rsync同步操作、inotify实时同步、数据库服务基础 实操前骤:(所需tools.tar.gz与users.sql) 1.两台主机设置SELinnx和关闭防火墙 setenforce 0 systemctl stop firewalld.service //停止防火墙 sy…

MySQL定时备份数据,并上传到oss

1.环境准备 1.安装阿里云的ossutil 2.安装mysql 2.编写脚本 脚本内容如下 #!/bin/bash # 数据库的配置信息,根据自己的情况进行填写 db_hostlocalhost db_usernameroot db_passwordroot db_namedb_root # oss 存贮数据的bucket地址 bucket_namerbsy-backup-buck…

软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策

引言 原文链接 近日,一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新,如同一颗隐形炸弹在全球范围内引爆,…

Python面试宝典第17题:Z字形变换

题目 将一个给定字符串 s 根据给定的行数numRows ,以从上往下、从左到右进行Z字形排列。比如:输入字符串为"PAYPALISHIRING",行数为3时,排列如下。最后,你的输出需要从左往右逐行读取,产生出一个…

unity 实现图片的放大与缩小(根据鼠标位置拉伸放缩)

1创建UnityHelper.cs using UnityEngine.Events; using UnityEngine.EventSystems;public class UnityHelper {/// <summary>/// 简化向EventTrigger组件添加事件的操作。/// </summary>/// <param name"_eventTrigger">要添加事件监听的UI元素上…

DevExpress中文教程 - 如何在.NET MAUI应用中实现Material Design 3?

DevExpress .NET MAUI多平台应用UI组件库提供了用于Android和iOS移动开发的高性能UI组件&#xff0c;该组件库包括数据网格、图表、调度程序、数据编辑器、CollectionView和选项卡组件等。 获取DevExpress v24.1正式版下载 Material Design是一个由Google开发的跨平台指南系统…

HydraRPC: RPC in the CXL Era——论文阅读

ATC 2024 Paper CXL论文阅读笔记整理 问题 远程过程调用&#xff08;RPC&#xff09;是分布式系统中的一项基本技术&#xff0c;它允许函数在远程服务器上通过本地调用执行来促进网络通信&#xff0c;隐藏底层通信过程的复杂性简化了客户端/服务器交互[15]。RPC已成为数据中心…

【Hot100】LeetCode—279. 完全平方数

目录 题目1- 思路2- 实现⭐完全平方数——题解思路 3- ACM 实现 题目 原题连接&#xff1a;279. 完全平方数 1- 思路 思路 动规五部曲 2- 实现 ⭐完全平方数——题解思路 class Solution {public int numSquares(int n) {// 1. 定义 dpint[] dp new int[n1];//2. 递推公式…