牡丹江建设银行网站/广东新闻今日最新闻
前言
2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD。快二十年的时间,领域驱动设计在不断地发展,后微服务时代强调的东西,在国外大家都热衷于领域驱动设计解决业务复杂度,在国内吧,我发现除了大厂以外,你和他说,完全不明白,可能很多人对于什么是面向对象开发,都不明白,什么才是真正的面向对象开发;也是在学习中成长着,我建议是从 《设计模式-可复用面向对象软件的基础》 《领域驱动设计:软件核心复杂性应对之道》《实现领域驱动设计》《解构领域驱动设计》 等等这些书看着走,多在项目中实践,就会明白它想给我们创建一个怎样的软件,如何用领域驱动设计应对当今这些复杂的业务逻辑。
首先都是思想(不是技术),我们要明白;所以它很抽象,很难总结出一套方法解构论,就是很抽象,抽象的东西理解起来就很困难,这就是为什么国内一直 想用,但非常难;其实到 解构领域驱动设计 这本书 21 年出版的,我渐渐地发现吧,已经在往“八股文”方向套了;要不然你看前两本书 全是概念,除了大神还可以摸索出来,但是一般人使用了反而更拉。
可以推荐大家 一个学习ddd的网站的,国内的。
https://www.jdon.com/ddd.html
什么是DDD
领域驱动设计(Domain-Driven Design,简称DDD)
业务初期,我们的功能大都非常简单,普通的CRUD就能满足,此时系统是清晰的。随着迭代的不断演化,业务逻辑变得越来越复杂,我们的系统也越来越冗杂。模块彼此关联,谁都很难说清模块的具体功能意图是啥。修改一个功能时,往往光回溯该功能需要的修改点就需要很长时间,更别提修改带来的不可预知的影响面。
原型 实体 值对象 ,构成聚合根,都在一个领域里面的。 主要是将领域划边界,方法和领域共存, 然后控制出 领域里面的行为 (方法) 其实将业务服务打的更散,放到对象中, 后面的变化不断应对,后期维护是相当快的。 贫血模型 和充血模型, 这个概念后面说一下。

在刚开始开发的时候,我们是这么设计的,随着我们的业务不断发展,我们的项目不断扩大,同时我们的表也是一个订单大表,包含了非常多字段。在我们维护代码时,牵一发而动全身,很可能只是想改下商品的功能,却影响到了创单核心路径。虽然我们可以通过测试保证功能完备性,但当我们在订单领域有大量需求同时并行开发时,改动重叠、恶性循环、疲于奔命修改各种问题。
上述问题,归根到底在于系统架构不清晰,划分出来的模块内聚度低、高耦合。
订单商品模块,假设我们随着数据库区设计:
首先建立模型:
class goods{String id;//主键String skuId;//唯一识别号String goodsName;Bigdecimal price;Category category;//分类List<Specification> specifications;//规格 ...
}class Order{String id;//主键String orderNo;//订单号List<OrderItem> orderItems;//订单明细BigDecimal orderAmount;//总金额...
}class OrderItem{String id;Goods goods;//关联商品BigDecimal snapshotPrice;//下单时的价格
}
考虑到了订单要保存下单时候的价格(当然,这是常识)但这么设计却存在诸多的问题。在分布式系统中,商品和订单这两个模块必然不在同一个模块,也就意味着不在同一个网段中。上述的类设计中直接将Product的列表存储到了Order中,也就是一对多的外键关联。这会导致,每次访问订单的商品列表,都需要发起n次远程调用。
反思设计,其实我们发现,订单BC的Product和商品BC的Product其实并不是同一个entity,在商品模块中,我们更关注商品的规格,种类,实时价格,这最直接地反映了我们想要买什么的欲望。而当生成订单后,我们只关心这个商品买的时候价格是多少,不会关心这个商品之后的价格变动,还有他的名称,仅仅是方便我们在订单的商品列表中定位这个商品。
重点是,领域设计思路需要去脱离数据库的桎梏,最高的预期是根据界限去完成数据库设计,最次。。不需要数据库来绑架我们的系统设计。业务才是王道,一个架构师的核心价值不仅仅体现在框架的应用上,最关键在于能够将我们的系统设计安排得明明白白。
如何改造
class OrderItem{String id;String productId;//只记录一个id用于必要的时候发起command操作String skuId;String productName;...BigDecimal snapshotPrice;//下单时的价格
}
做了一定的冗余,这使得即使商品模块的商品,名称发生了微调,也不会被订单模块知晓。这么做也有它的业务含义,用户会声称:我买的时候他的确就叫这个名字。记录productId和skuId的用意不是为了查询操作,而是方便申请售后一类的命令操作(command)。
在这个例子中,Order 和 goods都是entity,而OrderItem则是value object(想想之前的定义,OrderItem作为一个类,的确是描述了Order这个entity的一个属性集合)。关于标识,我的理解是有两层含义,第一个是作为数据本身存储于数据库,主键id是一个标识,第二是作为领域对象本身,orderNo是一个标识,对于人而言,身份证是一个标识。而OrderItem中的productId,id不能称之为标识,因为整个OrderItem对象是依托于Order存在的,Order不存在,则OrderItem没有意义。
单根 聚合根
在《解构领域驱动设计》 这本书中 是将聚合作为边界的象征,作为所有领域的入口。
聚合(aggregate)是一种边界’它可以封装_到多个实体与值对象’并维持该 边界范围之内的业务完整性°聚合至少包含_个实体’且只有实体才能作为聚合根(aggregateroot)。 工厂(鱼ctory)和资源库(repository)(参见第17章)负责管理聚合的生命周期。前者负责聚合的 创建’用于封装复杂或者可能变化的创建逻辑;后者负责从存放资源的位置(数据库、内存或者其 他Web资源)获取、添加、删除或者修改聚合。
要访问聚合只能通过聚合根的资源库,这就隐式地划定了边界和 入口,有效控制了聚合内所有类型的领域对象。若聚合的创建逻辑较为复杂或存在可变性’可引入工 厂来创建聚合内的领域对象·
聚台的定义与特征
Eric Evans阐释了何谓聚合(aggregate)模式:“将实体和值对象划分为聚合并围绕着聚合定义 边界。选择-个实体作为每个聚合的根’并允许外部对象仅能持有聚合根的引用。作为_个整体来 定义聚合的属性和不变量’并将执行职责赋予聚合根或指定的框架机制°”这一定义说明了聚合的 基本特征。
聚合是包含了实体和值对象的—个边界。 聚合内包含的实体和值对象形成-棵树’只有实体才能作为这棵树的根°这个根称为聚合 根(aggegateroot)’这个实体称为根实体(rootentity)° □外部对象只允许持有聚合根的引用, 以起到边界的控制作用。 □聚合作为_个完整的领域概念整体’其内部会维护这个领域概念的完整性,体现业务上 不变量约束° □由聚合根统_对外提供履行该领域概念职责的行为方法,实现内部各个对象之间的行为 协作。

类似于

四种领域模型
失血模型
贫血模型
充血模型
胀血模型
修改商品为例来举例模型的概念
class goods{String id;String skuId;//唯一识别号String goodsName;
}
失血模型**:略过,可以理解为所有的操作都是直接操作数据库。
贫血模型:
class GoodsDao {@AutowiredJdbcTemplate jdbcTemplate;public void updateName(String name,String id){jdbcTemplate.excute("update goods u set u.goods_name = ? where id=?",name,id);}
}class UserService{@AutowiredUserDao userDao;void updateName(String name,String id){userDao.updateName(goodsName,id);}
}
贫血模型中,dao是一类sql的集合,在项目中的表现就是写了一堆sql脚本,与之对应的service层,则是作为Transaction Script的入口。观察仔细的话,会发现整个过程中user对象都没出现过。
充血模型
interface UserRepository extends JpaRepository<Goods,String>{//springdata-jpa自动扩展出save findOne findAll方法
}class UserService{@AutowoirdUserRepository userRepository;void updateName(String name,String id){Goods goods = goodsRepository.findOne(id);goods.setName(name);goodsRepository.save(user);}
}
充血模型中,整个修改操作是“隐性”的,对内存中goods对象的修改直接影响到了数据库最终的结果,不需要关心数据库操作,只需要关注领域对象goods本身。Repository模式就是在于此,屏蔽了数据库的实现。与贫血模型中goods对象恰恰相反,整个流程没有出现sql语句。
涨血模型:
没有具体的实现,可以这么理解:
void updateName(String name,String id){Goods goods = new Goods(id);goods.setName(name);goods.save();
}
我们在Repository模式中重点关注充血模型。
实体 值对象
在领域驱动模型中,战术模型:

实体
实体(entity)这个词被我们广泛使用’甚至过分使用。设计数据库时,我们用到实体, Len Silverston就说:“实体是一个重要的概念,企业希望建立和存储的信息都是关于实体的信息。’’在分解系统的组成部分时’我们用到实体’EdwardCrawley等人就说:“实体也称为部件、模块、 例程、配件等’就是用来构成全体的各个小块°”
一个典型的实体应该具备3个要素:
身份标识;
属性;
领域行为°
根据ID的共同特征’可以定义一个通用的接口:

通用类型和领域类型ID的区别仅在于值是否代表丁业务含义。作为实体的身份标识,它们都 具有业务价值
实体的属性用来说明主体的静态特征,并持有数据与状态。通常,我们会依据粒度的粗细将 属性分为原子属性与组合属性。定义为开发语言内建类型的属性就是原子属性’如整型、布尔型、 字符串类型等,表述了不可再分的属性概念。
领域行为
实体拥有领域行为,可以更好地说明其作为主体的动态特征。
值对象
值对象(valueohject)通常作为实体的属性,也就是亚里士多德提到的分量、性质、关系、场 所、时间、位置姿态等范畴。正如Eirc Evans所说,“当我们只关心一个模型元素的属性时,应把 它归类为值对象°我们应该使这个模型元素能够表示出其属性的意义,并为它提供相关功能。值对 象应该是不可变的。不要为它分配任何标识′而且不要把它设计成像实体那么复杂 。“
值对象与实体的本质区别
一个领域概念到底该用值对象还是实体类型,第一个判断依据是看业务的参与者对它的相等
判断是依据值还是依据身份标识°—前者是值对象’后者是实体。
值对象具有的特性:
对象创建以后其状态就不能修改;
对象的所有字段都是final类型;
对象是正确创建的(创建期间没有this引用溢出)。
领域行为 : 值对象的名称容易让人误会它只该拥有值’不应拥有领域行为。
实际上,只要采用了对象建 模范式,无论实体对象还是值对象,都需要遵循面向对象设计的基本原则,如信息专家模式,将操 作自身数据的行为分配给它。EircEvans之所以将其命名为值对象,是为了强调对它的领域概念身 份的确认,即关注重点在于值。

微服务架构中的DDD应用
在微服务架构中,我们提倡的是低耦合,高内聚,那么需要达到低耦合高内聚这个目标,我们需要去如何应用DDD领域的概念去完成呢?
在DDD领域中,提供了我们一个非常有意思的东西,叫做界限上下文.界限上下文是怎么来的,我们肯定需要知道,我们要理解一个领域的概念。
以服务端而言,我们需要来界定领域,这时候我们需要来对需求文档进行分析:
根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;
进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;
对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;
为聚合根设计仓储,并思考实体或值对象的创建方式;
在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。
领域
现实世界中,领域包含了问题域和解系统。一般认为软件是对现实世界的部分模拟。在DDD中,解系统可以映射为一个个限界上下文,限界上下文就是软件对于问题域的一个特定的、有限的解决方案。
那么我们的服务端假设只有两个领域--一个是订单,一个是商品,那么我们可以把商品领域进行进一步的细分:
假设商品需求如下(事实上这个和用户角色进行了挂钩,我们先不用去太在意这个,先来理解下领域):
买方商品--可见购买商品,购买者可以看到所有商品(进行价格排序)。
卖方商品--可以去上架商品,上架成功之后购买者就能够看到商品。
供应商商品--可以给销售者提供商品,销售者的商品需要在销售列表中可被选择。
在每一个边界就形成了界限上下文。
在进行上下文划分之后,我们还需要进一步梳理上下文之间的关系。
康威(梅尔·康威)定律任何组织在设计一套系统(广义概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。
康威定律告诉我们,系统结构应尽量的与组织结构保持一致。这里,我们认为团队结构(无论是内部组织还是团队间组织)就是组织结构,限界上下文就是系统的业务结构。因此,团队结构应该和限界上下文保持一致。
拓展:墨菲定律--每当你觉得可能会发生的时候,这件事一定会发生。
通过我们界限上下文的划分,我们可以开始对商品服务内部进行处理:
import com.dn.goods.bussiness.buyer.;//买方上下文
import com.dn.goods.bussiness.seller.;//卖方上下文
import com.dn.goods.bussiness.supplier.*;//供应商上下文
整个DDD领域驱动设计,国内还不够成熟,对于小型的项目,我觉得可以使用来作为实验,因为很多时候,你在说撒,可能别个都不懂,这就很尴尬了,更不用说是开发东西了。
相关文章:

DDD单根 聚合根 实体 值对象
前言2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD。快二十年的时间,领域驱动设计在不断地发展,后微服务时代强调的东西,在国…...

SpringMvc介绍。
目录 1、SpringMvc概述 1、基本介绍 2、工作流程 3、bean加载控制 二、请求 1、请求映射路径 2、请求方式 3、请求参数 4、请求参数(传递json数据) 5、日期类型参数传递 三、响应 四、REST风格 1、REST简介 2、RESTful入门案例 3、RESTfu…...

华为OD机试 - 最小传递延迟(JS)
最小传递延迟 题目 通讯网络中有N个网络节点 用1 ~ N进行标识 网络通过一个有向无环图进行表示 其中图的边的值,表示节点之间的消息传递延迟 现给定相连节点之间的延时列表times[i]={u,v,w} 其中u表示源节点,v表示目的节点,w表示u和v之间的消息传递延时 请计算给定源节点到…...

学生信息管理系统(通讯录)----------通俗易懂、附源码、C语言实现
绪论: 本篇文章使结构体章节后的习题,如果你对C语言有问题,或者结构体有什么问题不妨看看我之前所写的文章(章回体),对于文件管理和内存分配问题我将在后面补上,对于这个学生信息管理系统我用了多种方法和…...

Python抽奖系统
#免费源码见文末公众号# 抽奖系统① def choujiang1():def write():with open(d:\\抽奖系统\\抽奖1.1.pickle,rb) as file:lst1pickle.load(file)namevar1.get()if name not in lst1 and name!录入成功! and name!录入失败! and name!:lst1.append(name)…...

真实景观渲染技巧【Three.js】
受到一些很棒的 three.js 演示、与 covid 相关的旅行禁令以及可能在 pinterest 上花太多时间看美丽的旅行照片的启发——我开始看看我是否可以使用 three.js 和r3f在浏览器中渲染一个令人信服的风景场景。 推荐:将 NSDT场景编辑器 加入你的3D开发工具链。 在过去一个…...

MySQL知识汇总:MySQL函数CASE WHEN用法详解
Case When的两种简单用法 用法一: CASE seasonWHEN Spring THEN 春天 WHEN Summer THEN 夏天 WHEN autumn THEN 秋天 else 冬天 end 用法二: CASE WHEN season Spring THEN 春天WHEN season Summer THEN 夏天WHEN season autumn THEN 秋天 els…...

Python学习-----模块1.0(模块的简介、定义与使用)
目录 前言: 1.什么是模块 2.模块的分类 (1)内置模块 (2)第三方模块 (3)自定义模块 3.模块的使用 4.自定义模块 5.模块和执行文件的判断 前言: 今天就开始讲Python中的模块篇…...

Linux进程学习【二】
✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…...

我问chatGPT,在JavaScript中构造函数和类的区别
问:构造器函数和面向中的类是同样的东西吗|? 答:构造器函数和面向对象中的类并不是同样的东西,它们之间有些许不同。 在面向对象编程中,类是一种抽象的概念,它描述了一类具有相同属性和行为的对象。类可以…...

软考高级-信息系统管理师之沟通管理(最新版)
项目沟通管理 1、项目沟通管理基础项目沟通管理的重要性项目沟通管理相关理论2、规划沟通管理3、管理沟通4、控制沟通项目沟通管理的技术和工具1、项目沟通管理基础 项目沟通管理的重要性 1、与1T项目成功有关的最重要的四个因素是:主管层的支持、用户参与、有经验的项目经理…...

PyQt5 自定义富文本编辑器
介绍 一款使用PyQt5和网页端框架wangEditor集成的富文本编辑器 代码片段 PyQt5客户端 与网页端建立连接def create_connect(self):self.web_view QWebEngineView()self.bridge JSBridge(self.web_view.page())self.web_view.load(QUrl.fromLocalFile(self.editor_path))w…...

【高可用系统架构设计】SLA服务可用性4个9是什么意思?如何保证服务的高可用性 HA(High Availability)?...
如何保证服务的高可用性 HA(High Availability)?高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。方法论上,高可用是通…...

微服务架构设计模式-(14)面向生产环境
生产环境要求 应用安全 数据权限 服务可配置性 不同环境的配置不一样,不能写死代码,所以要配置 可观测性 需要日志系统 应用安全 四个方面 身份验证 验证主体的身份解决方案 单体 cookie 微服务中 API Gateway 访问令牌 不透明令牌透明令牌ÿ…...

HTML5新增用法
新增语义化标签 并无特殊含义,是语义!语义!语义! <header> 头部区域 <nav> 导航区域 <main> 主体区域 <article> 内部标签 <section> 块级标签 <aside> 侧边栏标签 <footer> 尾部…...

富足金字塔:人的努力是为了扩大选择的范围
人的努力是为了扩大选择的范围,这是熵减的另一种表述。富足金字塔代表着人生的三重境界。第一层是温饱。人需要食物、水、住所。第二层是品质。能源、ICT、教育带来更有品质的生活,如智能门锁、智能马桶、扫地机、洗碗机、洗衣烘衣机。第三层是梦想。包括…...

C++类基础(十七)
类的继承——补充知识 ● public 与 private 继承(C Public, Protected and Private Inheritance) 改变了类所继承的成员的访问权限 //公有继承 struct Base { public:int x; private:int y; protected:int z; }; struct Derive : public Base //公有继承…...

LeetCode刷题复盘笔记—一文搞懂贪心算法之56. 合并区间(贪心算法系列第十四篇)
今日主要总结一下可以使用贪心算法解决的一道题目,56. 合并区间 题目:56. 合并区间 Leetcode题目地址 题目描述: 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间…...

Andriod入门级开发
这学期有个课设,我们组我负责一个手机APP的开发,虽然刚开始说要实现什么智能导航,类似高德地图那种,但最后阉割的只剩一个Socket通信了,因为之前没有接触过(可能之后也不会再接触),记…...

DCL 数据控制语言
1、简介 DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。 2、管理用户 2.1 查询用户 select * from mysql.user;查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问…...

全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机
文章目录1. 文章引言2. 下载VMware3. 安装VMware1. 文章引言 我们使用最多的系统是windows系统,因为,国内电脑厂商的操作系统(os)基本是windows系统,比如华为、联想、华硕等电脑。 但线上的服务器大多是Linux系统,而我们经常使用…...

Python获取zabbix问题触发器
背景:阿里云的ECS服务器因为阿里云升级插件,导致安全防护程序重启,产生不同的端口。导致低自动发现注册的端口 大量报警。 解决:杀掉关于因为非业务 变更的端口检测的触发器。 相关文档: Zabbix监控之主机端口监控自…...

原型链污染
目录 前置知识 原型对象 prototype和__proto__的区别 原型链概念 原型链的继承 原型 链污染 原型链污染原理 javascript中可能会存在原型链污染的危险函数 原型链污染的实际应用 JavaScript中可以触发弹窗的函数 前置知识 原型对象 在JavaScript中,每个函…...

ClickHouse详解
一、概念ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。OLAP场景的关键特征绝大多数是读请求数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。已添加到数据库的数据不能修改。对于读取,从数据库中提取相当多的…...

02_Docker 安装
02_Docker 安装 文章目录02_Docker 安装2.1 安装 Docker 的先决条件2.2 在 Ubuntu 和 Debain 中安装 Docker2.2.1 检查前提条件1. 内核2.检查 Device Manager2.2 安装 DockerDocker 支持非常多的Linux平台,包括Ubuntu和RHEL,除此之外,Docker还…...

K8S集群将Docker切换到Containerd
文章目录1. 开启节点维护1.1 将节点设置成不可调度1.2 驱逐节点上的 Pod1.3 停止相关服务2. 升级到 containerd2.1 安装 containerd2.2 调整 containerd 配置2.3 修改 kubelet 启动配置参数3. 重启节点服务4. 验证升级后的节点5. 容器管理工具5.1 容器管理命令行工具对比5.2 cr…...

Kubernetes03:kubernetes 功能和架构
2.1 概述 Kubernetes 是一个轻便的和可扩展的开源平台,用于管理容器化应用和服务。通过 Kubernetes 能够进行应用的自动化部署和扩缩容。在 Kubernetes 中,会将组成应用的容 器组合成一个逻辑单元以更易管理和发现。Kubernetes 积累了作为 Google 生产环…...

LabVIEW中CPU和内存使用情况在NI分布式系统管理器中不可见
LabVIEW中CPU和内存使用情况在NI分布式系统管理器中不可见想使用NI分布式系统管理器监测网络连接实时控制器的CPU和内存使用情况。从左侧窗口的树中选择了感兴趣的实时目标,然后通过选择视图自动视图来确保启用自动查看。希望看到CPU/内存选项卡,但它有显…...

buu [NPUCTF2020]Classical Cipher 1
题目描述: 题目分析: 首先输入密码 {gsv_pvb_rh_zgyzhs} 后,得到:可以得知密码是错误的,再看看密码 {gsv_pvb_rh_zgyzhs} ,排列无序,那么尝试用凯撒与栅栏解密,发现还是解不出&…...

分享96个HTML体育竞技模板,总有一款适合您
分享96个HTML体育竞技模板,总有一款适合您 96个HTML体育竞技模板下载链接:https://pan.baidu.com/s/1k2vJUlbd2Boduuqqa0EWMA?pwdj8ji 提取码:j8ji Python采集代码下载链接:采集代码.zip - 蓝奏云 北京奥运火炬PSD模板 奥运…...