领域驱动设计:实战
领域驱动设计 -- 概念
领域驱动设计 -- 方法论
领域驱动设计 -- 实战
实战描述模型分析设计中需要遵循的过程及设计方法,供模型设计参考,以构建高质量的模型。文章描述的内容建立在业务领域规划指导下,建立应用模型的规范,包含对概念模型、逻辑模型、物理模型的分析和设计方法相关的内容。下面跟大家分享9年前在做企业应用软件时的模型设计方法
模型设计方法
1. 总论
1.1 规划方法总图
image.png1.2 规划过程
image.png需求调研阶段对应“规划方法总图”第二列 image.png
在规划的过程中,我们按照上图3箭头的方向进行,在矩阵的每个格子中同时做ER和DFD两方面的分析和设计
1.3 分析设计原则
整个模型设计的过程是一个从整体到局部、从高层模型设计到细节逐步细化的过程。模型设计过程可以分为三个阶段:
1》概念分析阶段
2》逻辑设计阶段
3》物理设计阶段
1.4 3X3矩阵
3X3矩阵是方法论在模型设计各阶段关注点的整体描述,系统设计的整个过程都是围绕3X3矩阵依次进行的
image.png横向分为概念、逻辑、物理阶段,这是软件工程角度的划分 image.png
纵向分为业务、管理、实现三个层面,这是业务角度上的划分,它们之间是一种并列关系,但是它们之间互相联系,只是它们各自关注的角度不同
》业务
处理核心业务事件(直接使客户受益的活动),该类业务活动的某环节一旦停止,业务即不能正常开展
》管理
处理为了使业务运转的更好所增加的管理、监控类活动,主要分以下两类:一类是对活动本身的监控与管理,即规则管理;另一类是对活动结果的监控与管理,如经营分析
》实现
处理为了使核心业务流程能够正常运转所需要开展的辅助活动,明确业务限制条件。如:异常处理,支持与就绪,与参与人的交互等
1.2 模型推导方法概述
1.2.1 活动的推导方法
使用ER对活动(组成整个流程中的具体的处理点)进行建模,是对传统ER建模的扩充。这种方法适用于对业务活动、管理活动等动作的建模,针对于业务系统或者系统中的活动。一个活动的产生至少需要两个参与者,这两个参与者之间因为活动而产生的关系必然是多对多关系
如何识别业务活动?
1)从需求分析中的事件活动来
2)从动词文法分析
表示动作行为的动词,如:打、拿、批评、学习
如何推导?
首先2个实体之间多对多的关系进行平衡展开,步骤如下:
Lark20190331223640.png接着,对已平衡展开的活动进行分解:上层的活动进行分解成下层的多个活动;即下一层的所有活动完整支撑上一层活动。下一层的活动可能发生于下图中的橙色关系中的一种或多种。E1自关联活动、E2自关联活动、实例自关联活动,仍然菱形展开。自关联活动可能是实体自身之间、或者它的一个或多个子实体之间的活动。如下图: image.png
活动分解有两种情况:
并列子活动:子活动之间是并列执行的,某一子活动不依赖于某一子活动的执行结果 image.png
串行子活动:子活动的执行是有序的,某一子活动依赖于某一子活动的执行结果 image.png
1.2.2 静态关系
实体之间的静态关系一般表现为此时此地实体之间的从属、依赖、依存、分类等关系,传统的ER建模实践中最常见的就是从属关系,从属关系表现为一对多关系、分类关系
如何识别从属关系
1)从需求分析中的业务对象的组织结构、形式、状态等获取
2)从动词文法分析,表示关系和存在的动词(静态类动词),如:包含、构成、有、在、是等
image.png
3)分类 image.png
大部分的模型推导都是静态和活动两种推导方法
1.3 模型对到前准备
借鉴行业成功经验整理出来的信息需求是信息及模型设计的关键输入,也是衡量模型设计质量的标准。好的模型设计的首要因素是对业务的理解,包括对现有业务运营模式的理解以及业务发展趋势的分析,而不是模型设计的方法和技巧
和模型设计相关的需求收集与分析主要包括以下一些方面:
》模型设计目标以及覆盖业务范围的定义,以确定模型设计需要包含哪些信息和数据
》模型设计时间进度的要求,以确定计划投入的资源
》收集整理业务概念、术语、信息及数据的处理规则
》分析影响业务运营成功的关键因素,也就是核心的业务运营理念,以及支撑这些因素所需要的数据。例如以客户为中心是一个关键的业务运营模式,在数据层面如何有效的支撑。
》性能相关的信息,如业务的规模、吞吐量、相应时间的要求等,以确定性能设计方面需要考虑的问题以及解决方案(主要在物理模型设计阶段考虑相应的解决方案)
》对应用系统期望的有效运行期限,以及在有效期内业务变化的可能性的分析,这些信息会影响期望模型支持哪些层次上的变化
》对已有应用系统的模型的分析,也是新的模型设计的重要信息来源
1.4 概念模型分析阶段
概念模型是技术中立的,从业务的视角对企业运营过程中涉及的信息进行结构化描述,是高层次的粗粒度的模型,是对现实世界问题空间的IT表达(信息模型),不包含设计实现细节的设计模型
概念模型是对企业业务运营过程中涉及的信息的结构化描述;是技术中立的模型;是从业务的视角对信息的结构化描述,通过关键的实体、关系、规则的描述定义关键业务概念;概念模型是分析模型
》输入:规范、需求文档;其它相关模型文件等;业务目标、范围与定位
》输出:概念阶段ERD、概念阶段DFD、概念阶段事件列表、概念阶段交叉校验、业务场景验证文档、业务功能与角色对应关系
1.4.1 目的
概念分析用IT语言表达现实世界问题,通过对业务和管理方面的分析,分析出所有的业务概念实体,定义业务概念,阐述清楚实体之间的基本关系,确定业务概念的关键属性及其值域
1.4.2 分析步骤
》初步划分业务活动范围
》寻找业务活动范围中的业务实体并描述定义
》分析并描述业务实体之间的关系:从属关系分析;业务处理活动分析;管理活动分析
》分析并描述业务实体关键属性
》分析属性所对应的业务值域
》业务场景校验、CRUD校验
概念模型的工作
》目标:对关键业务实体、实体关系、相关业务规则建模,形成高层次的实体关系图
》寻找并描述与实体类、关系相关的业务规则
》从高层概念引出要分析的核心实体,以及之间的关系
》核心实体进行定义,以期大家对某个概念统一认识
》将活动按菱形展开,所有的一级的活动全部展开
》将从属关系进行描述
》将上级的活动分解成更细粒度的二级活动
》继续分解,直到分解到直接业务人员不可见为止
》分别将业务活动、管理活动、实现层面活动分解到位
注意事项
》只分析业务人员角度可见的ER关系
》不可以系统中如何设计的角度(系统实现角度)分析ER
》活动的展开使用菱形展开方法
》实体可以增加核心属性
1.4.3 分析实战
1. 承接
要么承接企业级概念模型,要么从最头上的业务活动推导到领域核心业务活动。比如业务活动,最初的起点在业务活动的参与人之间的经济活动,对其进行建模,并且按照菱形展开方式进行推导。以参与某活动为例: image.png然后,根据我们分析的业务领域,按照“生产关系”这个纬度将“参与人”实体进行分类,分为“消费者”和“生产者”,并且对“消费者”和“生产者”这两个业务概念进行定义(这里就不写出了) image.png
然后,“参与人”自身的“经济活动”关系就具体化为“消费者”和“生产者”之间的“等价交换”关系(活动)
image.png
之后,“等价交换”活动可按照菱形方式进行平衡展开
2. 获取业务概念
1)框定业务范围
在本文档里业务范围我们也称为业务领域。是我们要研究的跟某个核心事物相关的具体的业务集合。
如果有业务文档,我们可以从业务文档中搜寻业务实体和业务事件。
2)寻找关键业务概念,转变为关键业务实体,形成实体的定义;
比如第一节中,寻找的关键业务词汇:参与人、生产者、消费者、经济活动(开展经济活动)、等价交换;其中“参与人”、“生产者”、“消费者”均为名词、业务活动的参与者、承载者,可以形成实体。
3)根据业务事件寻找并定义关键业务实体之间存在的关联关系;
关键业务词汇中的“经济活动(开展经济活动)”、“等价交换”是业务活动、表示动作的动词,抽取出来作为业务承载者之间的活动类关系。
根据参与人可以分为生产者和消费者,我们可以获取这3个业务概念(实体)之间的静态类关系,这样就获得了3者之间的分类关系。
4)分解过程中,核心属性如果需要进行深入分析,或者其在业务要求使得它不具备原子性,需要将其拉出来作为一个实体,进行研究。
3. 获取业务活动
列出业务层面的事件列表,将业务处理活动逐层地进行分解。
从需求文档或者参考资料整理出业务事件,形成事件列表,按照层级进行展现;例如下表余额管理的事件列表: image.png
业务活动的分析可以是一步到位的,也可以是逐步完善的(可能需要多次迭代)
4. 模型推导
根据实体之间的从属关系画出静态关系,将每个活动按照菱形展开的方式画出ERD。业务活动是分层的,所以对应的这些活动的ER展开图也是分层的。推导的过程中,每个实体都有来源,要么是通过从属关系分析出来的,要么是通过业务活动菱形展开推导出来的,是不能凭空出现的。
ER的推导是一个多次反复迭代的过程 image.png image.png image.png image.png image.png
在活动推导过程中,核心实体的核心属性会最早分析出来,并且有可能会在分析的过程中分离成一个单独的实体。在活动的推导的后期,给实体补充上业务关键属性、以及属性的值域。
5. 总图
将所有推导的最下层的ER图,按照业务、管理、实现3个层面分别合并到一张图上,静态关系合并到一张图上,形成概念阶段的ER总图 image.png6. 分析业务功能与角色对应关系
从分析中提取出参与人,一般这些参与人属于角色的范畴,单独指个体的比较少。将参与人和他参与的活动结构化展示出来,就可以构成“业务功能与角色的对应关系” image.png1.4.4 概念模型做到什么程度?
业务事件分解到业务操作员可见的事件为止,ER推导同步。如果有需求文档,若所有的需求ER图都体现了,就算做到位了;如果没有需求,从0层总图往下推导3层
1.5 逻辑模型分析阶段
逻辑模型设计是在概念模型设计的基础上扩展和细化形成的解决方案视角的模型。逻辑模型重在设计,而概念模型重在分析。逻辑模型从概念模型转换形成,有建模工具支持这种模型之间的自动转换。
》输入:概念阶段的输出物;需求类文档
》输出:逻辑阶段ERD、逻辑阶段DFD、逻辑阶段交叉校验、概念阶段与逻辑阶段实体对应关系、概念阶段与逻辑阶段功能对应关系、业务场景验证文档、功能列表
1.5.1 目的
逻辑模型设计的目标就是设计支持现实世界概念模型的逻辑模式和子模式(外模式),将概念模型转换为某类数据库(关系或对象数据库)所支持的数据模型。在该过程中需要对概念设计阶段中牵涉的业务,逐步细化,以达到能在系统中实现。为此,需要从业务功能中抽象出处理功能,并且对实体和处理进行归纳抽象。并且在分析数据流时,要表达出具体数据的流向。
逻辑模型是在概念模型设计的基础上,加入设计的因素,对模型元素进行细化和扩充,并逐步应用规范化的策略对数据规范化,消除数据冗余,形成理想结构的详细的模型。逻辑模型是从解决方案的角度对数据的结构化描述;逻辑模型仍然是技术中立的模型,用于指导系统建设的模型设计。但逻辑模型并不是系统的数据结构,系统建设时,仍然需要在逻辑模型的指导下做进一步的设计,并进行物理模型的设计,形成最终的系统数据结构。
1.5.2 设计步骤
》在概念分析的基础上划定系统边界
》去除仅仅代表业务概念,而不需要应用系统实现的实体和处理
》将模型转化为关系模式
》将模型中相近的实体和处理进行归纳抽象,消除冗余
》引入设计层面所需要的实体和处理,并逐层细化
》设计实体类的属性,设计相关的值域,确定实体类的候选标识并进一步确定主标识,建立与属性相关的业务规则
》定义逻辑实体和处理
》业务场景校验、CRUD校验
逻辑设计的工作
》在概念模型分析的基础上,设计出展现系统中如何进行实现这一视角的ER模型。
》确定系统范围与边界
》去除仅仅代表业务概念,而不需要应用系统实现的实体类
》将概念模型中相近的实体进行归纳、分解
》按照规范化理论,对数据模型逐步规范化,去除冗余,使模型结构更为清晰、规范
》引入设计层面所需要的实体类,包括为分解多对多关联关系引入的实体类,解决继承关系引入的实体类,增加新的设计实体类
》设计实体类的属性,设计相关的属性域,确定实体类的候选键并进一步确定主键,建立与属性相关的业务规则
注意
》逻辑模型仍然是一个技术中立的模型,逻辑模型的设计不要过多考虑关于性能方面的问题,也不要考虑数据如何分布、存储
》最终设计出全属性模型
》通过和DFD进行交叉验证找问题
1.5.3 逻辑设计实践
1. 确定范围
概念模型分析的比较全,在逻辑阶段要进行细化、抽象和取舍,这里说一下取舍。取舍是基于概念模型,在概念阶段考虑实现层面的时候进行的动作。主要是由于项目的原因、业务领域与其它领域交互的原因、技术难度等原因,人为地将逻辑设计的范围进行框定,并且将边界的设计增加上。
2. 从概念模型转到逻辑模型
1)ER从属关系的转换
将E-R图转换为关系模型实际上就是要将实体、实体的属性和实体之间的联系转化为关系模式,这种转换一般遵循如下原则:
a. 概念层面的实体可直接转成逻辑实体。根据实体类、关联关系存在的相似性,进行适当层次的抽象,形成更为通用的概念;
b. 一个m:n联系转换为一个关系模式。与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性。而关系的码为各实体码的组合。
c. 一个1:n联系可以转换为一个独立的关系模式,也可以与n端对应的关系模式合并。如果转换为一个独立的关系模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为n端实体的码。
d. 一个1:1联系可以转换为一个独立的关系模式,也可以与任意一端对应的关系模式合并。
e. 三个或三个以上实体间的一个多元联系转换为一个关系模式。与该多元联系相连的各实体的码以及联系本身的属性均转换为关系的属性。而关系的码为各实体码的组合。
f. 同一实体集的实体间的联系,即自联系,也可按上述1:1、1:n和m:n三种情况分别处理。
g. 概念层面的实体属性可直接带到逻辑实体中,补充类型和长度等描述
2)归纳与细化
a. 对于实体进行完善、细化和抽象。
b. 将模型中相近的实体进行归纳抽象,消除冗余,从信息实体中提取出数据实体;抽象是一个由多到少的过程,目的是要达到模型与业务的无关性,实现数据模型的稳定持续发展
c. 抽象过程中属性和值域需做相应整合
d. 引入设计层面所需要的实体,然后对系统开展的活动进一步细化,使得处理功能越来越逼近于函数的实现形式;细化是一个由少到多的过程,细化的目标是完善实体和功能
e. 细化过程中需补充完整属性和值域
image.png image.png
3)业务活动向系统功能的转化:事件的抽象、合并与细化
image.png image.png image.png image.png
4)功能列表
a. 从业务事件获得系统功能
b. 功能继续进行分解、归纳迭代
image.png
5)业务实体归纳
image.png
6)属性与值域
a. 添加全属性、数据类型
b. 值域转换
7)结果图:将过程ER合并到结果图上
1.5.4 逻辑模型做到什么程度
直接转换成物理模型就可以在数据库里面生成正确的表结构
1.5.5 概念模型和逻辑的区别
从“业务范围”角度
概念模型》=逻辑模型(实体表示的业务范围上,不是实体数量)。
从“图”这个角度
概念模型的实体和逻辑模型的实体是多对多的关系。在确定的范围(逻辑实现范围)之内,概念模型的实体在逻辑模型中都能找到。
逻辑模型中不存在多对多关系。
概念模型的实体不要求画出所有的属性,逻辑模型要求是全属性的;数据类型的要求同上
1.6 物理模型分析阶段
物理模型是在逻辑模型设计的基础上,结合具体使用的数据库管理系统,加入对系统实现的考虑,包括系统的可实现性、系统的性能等。从实现的角度,在逻辑模型的基础上做必要的反向规范化的设计、模型物理结构的设计(包括索引设计、存储参数设计、视图设计、数据分割等),加入程序控制和动作控制
1.6.1 目的
物理模型设计的目标是根据DBMS特点和处理的需要,进行物理存储等安排;根据系统和用户数量对逻辑设计中模型的功能与实体进一步细化,使功能/数据能在具体的系统中实现,需要考虑效率、接口等问题。在该阶段还需做一些数据结构的冗余设计以提高数据访问的性能,包括增加冗余字段、增加派生字段、增加冗余表、对表结构重组、数据分割(水平分割、垂直分割),优化设计索引、调整数据库对象存储参数、设计视图等。
在做数据结构冗余设计的时候,要同时考虑数据完整性的保证机制。
》输入:逻辑阶段的输出物;需求类文档。
》输出:物理阶段ERD、物理阶段DFD、物理阶段与逻辑阶段实体对应关系、物理阶段与逻辑阶段功能对应关系、功能列表
1.6.2 设计步骤
》设计UI/系统接口
》考虑性能,进行反规范化设计
》设计数据存储(内存/文件/DB)
》设计索引、视图、分区、存储参数等性能参数
》引入具体实现层面所需要的实体和处理,并细化
》设计程序异常处理及系统管理
》设计其他技术实现细节
》场景校验、CRUD校验
1.6.3 物理设计实践
1. 逻辑模型转换为物理模型
1)转换到关系数据库
选定数据库,使用CASE工具(PowerDesigner)直接进行转换。
逻辑实体转换为数据库的物理表,关系转换为表间的外键约束,数据类型转换为具体DBMS的数据类型,逻辑值域转换为物理模型的值域。
2)转换到其它结构
内存数据库、内存、文件
2. 性能设计
1)性能需求
数据量:初始数据量有多少,每天或者每月的数据增量是多少?每天或者每月每个功能的数据增量是多少?
响应时间:关键业务的响应时间是多少
并发:高并发的业务(功能)是哪些?多少的并发量?
热点(数据的存取频度): 最多的数据读写发生在哪些表上?
2)性能设计的手段
分表
》水平分割:
根据一列或多列数据的值把数据行放到两个独立的表中。
应用场景
A 表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数,提高查询速度。
B 表中的数据本来就有独立性,例如表中分别记录各个地区的数据或不同时期的数据,特别是有些数据常用,而另外一些数据不常用。
C需要把数据存放到多个介质上。
》垂直分割:
把主码和一些列放到一个表,然后把主码和另外的列放到另一个表中。
应用场景
A 表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数,提高查询速度。
B 表中的数据本来就有独立性,例如表中分别记录各个地区的数据或不同时期的数据,特别是有些数据常用,而另外一些数据不常用。
C 需要把数据存放到多个介质上。
分表后,需要有相关的路由策略(比如路由表)保证对分出来的表的准确访问。
合表
在表结构类似的基础上,数据量不大,读写不频繁,可对表进行合并,合并的表可增加一个字段用以标识不同的业务数据。
冗余
最明显的打破范式的设计方法就是冗余法,以空间换取时间的做法,把数据冗余在多个表中,当查询时可以减少或者是避免表之间的关联。
冗余设计必须要有相应的措施保证数据一致性
索引
创建索引能明显提高数据的查询速度,但同时也增加了插入、更新和删除等维护任务的速度。合理的索引设计要建立在对各种查询的分析和预测上。定期做索引的碎片整理,定期进行表分析,以避免索引失效
1.6.4 物理模型设计到什么程度
就ER图上来说,表、字段、数据类型、主键、外键、唯一索引、索引、视图、触发器等定义完备,可直接生成建库脚本
1.6.5 逻辑模型与物理模型的区别
从“业务范围”角度
逻辑模型=物理模型(实体表示的业务范围上)。
从“图”这个角度
逻辑模型的实体和物理模型的表是一对一、一对多的关系占绝大多数。
物理模型中表的字段》=逻辑模型中实体的属性。
2. 模型验证
在模型分析设计阶段,都需要对模型设计的结果进行阶段性的验证,以及时发现模型设计中的问题,对模型及时更正
2.1 验证什么
模型验证,主要验证模型是否完整的支撑业务、支撑上一层的推导、设计是否合理、本层设计是否和上层有冲突、设计是否和业务有冲突。
模型验证需要考虑以下几个方面(以第一条和第二条为主):
》验证模型的完整性:模型是否覆盖需要的数据,是否能够满足业务需求,支持关键的业务运营模式和理念
》验证模型的可行性:模型是否简洁易懂,使业务人员能够准确把握和理解模型,基于模型的应用系统是否能够实现和实施
》验证模型的可复用性:模型的设计是否具有良好的通用性,能够被多个应用系统复用。模型的设计不能针对特定的应用系统组织和设计,否则很难具有良好的通用性
》验证模型的稳定性和灵活性:稳定性和灵活性是验证模型适应业务变化的能力。面对业务变化,模型不需要改变就能够适应业务需求,是模型稳定性的表现;当业务变化对模型产生冲击,通过对模型进行适当的扩展,而不影响已有的结构来适应业务需求,是模型灵活性的表现
2.2 验证手段
业务场景验证是验证模型和业务是否符合的手段,CRUD矩阵是验证设计是否合理的手段,ER和DFD的交叉验证用以验证推导过程是否一致
2.2.1 业务场景验证
首先,描述业务场景,即先拿出某个业务场景,获取参与人、流程、输入输出等相关信息,然后针对该业务场景的实现,一个步骤一个步骤地指出每个步骤分别是谁操作、读取什么输入、怎么加工、处理的规则是什么样的、处理结果保存到什么地方?即用数据模型说明清楚如何完美地表达这些业务场景。
如果,流程串不起来,或者该输入的数据找不到,或者输出数据没有地方保存,这些都是明显的错误,出现其中之一即为不通过。
2.2.2 CRUD验证
CRUD分别代表对数据的创建、读取、编辑更新和删除。CRUD验证的做法是:
将业务事件(活动、功能)和实体(属性、值域)分别放置到一个矩阵的行和列上,这样,每个业务事件就和每个实体都有一个交叉的格子,在每个格子里写上代表的业务事件对此实体操作的字母,如C(创建)R(读取)等,就构成了一个CRUD矩阵。
若出现上图右上角,两个实体(E2、E3)都被几个业务事件(P2、P3、P4)进行同样的操作(这里是C操作,比如同时还有同样的R操作等),那么这两个实体(E2、E3)可以考虑进行合并(当然还需要考虑这两个实体的属性是否具有相似性)。
两个业务事件(P2、P3)都对几个实体(E2、E3)进行同样的操作(这里是C操作,比如同时还有同样的R操作等),那么这两个业务事件(P2、P3)可以考虑进行合并(当然还需要考虑这两个业务事件还有没有其它的相似性)。
以上案例说明CRUD主要用于验证设计的合理性
2.2.1 ER和DFD交叉验证
对于一个活动,可以分别使用ERD和DFD的形式描述,DFD描述活动本身的过程,ER可以描述活动的过程,同时也能描述活动最后产生的结果、实体之间的静态关系。那么,用ER和DFD分别描述的某个活动,就其描述的过程和结果来说应该是一样的。
如果ER和DFD对于活动的表达不一致,那么说明二者的推导过程中至少有一个是错误或者不合适的