共计 6938 个字符,预计需要花费 18 分钟才能阅读完成。
背景
软件工程师做的外围事件就是对事实世界的问题进行形象而后用计算机的语言对其进行从新刻画,在通过信息化来进步生产力。而这其中一个关键环节就是如何对问题域进行建模,在过来的工作中常常遇到一个问题是后期因为业务比较简单所以设计的模型在撑持时没有发现什么问题而随着业务复杂度的减少就会发现须要对模型进行降级,如果是对模型关系维度的新增那还好,而如果是对原有模型关系的重构,那将会变的十分艰难。本文心愿可能通过总结过来本人对领域建模的一点浅显教训给须要的同学能有些许启发,少走弯路。
总体思维
对于如何建模并不是一个繁多维度的问题而是一个体系化的工程,咱们须要对其进行拆解而后一一攻破,如何建好模并能顺利落地能够拆分为四个子问题,1)对需要进行性能建模 2)对业务进行领域建模 3)将畛域模型映射到代码模型 4)依据代码模型落地数据模型。
- 需要模型:通过和产品及业务同学的沟通,联合行业教训和常识,明确用户的实在需要;
- 畛域模型:基于需要模型,提炼出畛域相干的概念,为前面的面向对象设计打下基础;
- 代码模型:以畛域模型为根底,综合面向对象的各种设计技巧,实现类的设计;
- 数据模型:以代码模型类及类之间的关系,用 ER 图刻画数据的底层存储关系;
还有一个重要的认知,领域建模并不是万能的,比方你做的零碎很简略,应用数据库的 CRUD 可能一个更好的形式 (如上图中的虚线箭头),如果做的是基础架构,比方开发一个 RPC 框架,也不须要用畛域驱动。使用畛域驱动的前提肯定是业务足够简单且多变,须要零碎灵便反对。上面这个图供参考:
需要建模
万事开头难,需要是我的项目最开始的输出,必定是十分重要的,但现实情况往往是当咱们接到需要后第一个想到的问题确是我该如何实现,而没有在业务思考这一块过多的停留。如果最开始了解的输出是谬误的,前面的过程再优良可想而知也只能是垃圾。为了解决这一问题,很多优良的大佬创造了很多对需要进行性能建模的工具,次要目标就是让咱们更好的了解需要并意识其背地的实质。如罕用的工具有 5w2h、业务流动、用户旅程、商业画布等。这些在网上都有很多的材料,只举几个例子,不做重点介绍。
- 业务流动
- 用户旅程
- 商业画布
领域建模
上面的每一种办法都是从某一个角度帮忙咱们更好了解客观事物,所以没有哪一种办法是万能的,在理论我的项目中经常要多种办法共用,才可能认清事件的全貌。
四步建模
在咱们日常工作的我的项目中,大多数场景都能够通过在需要用例中通过找名称的形式来最终刻画出畛域模型,当然找到的名词后并不是所有的都符合要求,这时能够通过一条准则 ” 一个名词或实体必有其属性和行为,一属性或行为也必归属于一个实体 ” 来进行提炼,不合乎这条准则的名词就是需要剔除的。总体来说建模一共分为四步
- 选名词:从用例中选出所有名词,在去伪存真选出符合要求的;
- 找动词:找出所有动词,在判断这些动词属不属于上一步选出的名词所具备的行为;
- 加属性:找出所有属性,在判断这些属性属不属于上一步选出的名词所具备的特色;
- 连关系:确定实体和实体之间的协作关系;
案例:用户购买商品
需要用例
建模步骤
第一步:选名词。从用例上选的名词如下:用户、购物 app、商品、用户档案、用户名称、地址、商家、订单、子订单、领取形式、银行卡、支付宝、微信。通过这种形式能够很轻松的辨认畛域中的相干概念,但选取的名词并不一定都是畛域相干的,所以接下来还须要进一步的提炼。提炼过程
- 删除 ” 购物 app”:购物 app 只是一个性能的载体,并不属于购买商品流量里的一个畛域概念,所以删掉
- 删除 ” 用户名称 ”:用户名称只是用户的一个属性,并不是畛域概念
- 删除 ” 地址 ”:地址只是用户档案的一个属性,并不是畛域概念
- 删除 ” 银行卡、支付宝、微信、领取形式 ”:银行卡、支付宝、微信属于领取形式的一种具体模式,而领取形式能够归属为订单的一个属性,并不是独立的畛域概念
所以最终提取的畛域实体是:用户、商品、用户档案、子订单、订单、商家
第二步:找动词。从用例上选的动词如下:选取、汇总、下单、保留、领取、勾销
找动词的目标是反向查看是否有脱漏的实体没有提炼进去,因为有些隐含的概念并不一定能在用例里找到,且一个动作必归属于一个实体。如果有发现动作没有归属实体只有 2 种状况,一是这个动作不属于这个畛域,二是有脱漏的实体没有提取进去。通过剖析 “ 选取 ” 是用户主观的一种行为,并不属于这个畛域所以删掉,” 下单、汇总、保留、领取、勾销 ” 都属于订单的动作。
第三步:加属性。实践上产品同学要在用例上把模型的所有属性全部列进去,但现实情况不肯定能做到,这时除了用例还须要当面和产品对焦分明各个模型的属性。
第四步:连关系。关系次要表白模型和模型之间怎么合作
补充场景:比方 “ 一个客户想入驻平台成为一个服务商 ”,依照上述办法提炼出动词 ” 入驻 ”,但会发现其并不适宜成为 ” 客户 ”、” 平台 ”、” 服务商 ” 实体的行为,因而能够反向推出还应存在另外一个实体 ” 入驻申请单 ” 的概念,” 入驻 ” 这个动词更精确的叫法是 ” 申请入驻 ”。
归类分组
归类分组,就是把具备相似性或相关联的信息,依照肯定的规范进行分类,归为同一个逻辑领域。“类”是一个极其重要的概念,能够看作实质雷同或类似的事物的汇合。分类就是依照肯定的规范,依据对象属性、特色的共同点和不同点,将对象划分为不同的品种。分类时,须要对这些类别进行鉴定、形容和命名。
分类在生活中无处不在。通过分类,一方面能够把杂乱无序的事物辨别开来;另一方面还要赋予不同类别以稳固的、概念化的名称。一个好的命名,可能简洁无力地表述事物的实质。分类的过程,就是探寻事物和问题实质的过程。
如何用归类分组进行领域建模能够分为 3 个步骤
第一步:定义要建模的畛域问题:也就是要分明咱们要解决的问题是什么?
第二步:对畛域问题进行拆解:对问题进行剖析拆解,造成平铺的多个子问题,此步骤能够尽量发散
第三步:归类分组:对子问题进行归类,剪枝,将趋同的子问题,合并成一类(能够了解问产出实体)
案例:生存服务类商品
生存服务类商品场景
- 预约类商品(KTV 预约、休娱预约、丽人预约等):
- 能够依照周期设置每周的价格;反对设定节假日的价格;
- 业务特点:商品价格同样呈周期性变动,有非凡日期以及不可用日期;计价形式包含按人、按间
- 场馆预约类
归类分组建模过程:
- 第一步:定义要建模的畛域问题:从下面的售卖商品场景能够看出一个商品有多个价格;而决定这个价格的是由一系列的因子决定的,有可能是 0 个也可能是多个;如何用一套齐备的价格模型来反对这些场景是须要解决的问题;
- 第二步:对畛域问题进行拆解:列举出所有商品价格的场景;
- 第三步:归类分组:
- 按人群、日期、阶梯、座位等类型,能够对立形象为价格的不同 ” 维度 ”
- 原价、起拍价、保证金、评估价等能够看做室价格的不同类型
所以一个价格由什么决定:sku 的价格 = 价格类型 + 价格维度 + 具体价格,具体形象过程如下:
- 第四步;产出畛域模型
案例:本地通商家成长
商家成长:为不同层级的商家门店下发不同类型的工作,实现对应的工作,商家会获取到对应的权利,进而帮忙商家在平台的不同阶段可能更好的成长。
- 第一步:定义要建模的畛域问题,针对门店维度为商家建设一套工作体系,不同的门店能够下发不同的系列工作
- 第二步:略
- 第三步:
1. 根底装修、商品优化、服务评估等属于一个维度,能够形象为 ” 工作流 ”
2. 门店图、手艺人、是否有品牌故事等属于一个维度,能够形象为 ” 工作 ”
3. 而由 ” 门店图、手艺人 ” 等工作组成的根底装修,能够形象为 ” 工作组 ”
4. 门店图片里又蕴含指标和实现的跳转动作,能够别离形象为 ” 工作指标 ”,” 工作动作 ”
- 第四步;产出畛域模型
事件风暴
为什么引入事件风暴。事件风暴之一的作用就是拉通业务方、产品、研发、测试对业务知识的对立了解,防止各方了解误差。但在实际操作中受限于各方工夫协调的难度及领域专家的角色的缺失,事件风暴往往作为了解业务,领域建模及畛域划分的利器去应用。
什么是事件风暴。事件风暴是一种以工作坊的形式对简单业务畛域进行摸索的高效合作办法,事件风暴强调以事件驱动团队摸索剖析业务畛域。
- 一种捕捉行为需要的办法
- 强调以先发散后收敛的形式发展
- 相干干系人合作的形式进行
- 重视对畛域事件的辨认
事件风暴相干元素
- 事件:重要且已产生的事件。命名形式:实现时 + 被动语态 = 宾语 + 动词过来式
- 命令:产生事件触发的动作
- 角色 / 执行者:触发命令的主体,包含:人员、零碎、定时工作
- 读模型:执行者决策执行命令时参考的视图元素
事件风暴操作流程
- 辨认重要事件
- 辨认命令
- 辨认执行者和读模型
- 辨认畛域对象
- 产出畛域模型
案例:销售根底
产品截图
- 辨认重要事件
- 辨认命令
- 辨认执行者和读模型
- 辨认畛域对象
这里说的畛域对象,是从命令、畛域事件、执行者、查问数据里找到的名词性概念。例如,对于签订合同这个命令而言,受到影响的名词性概念是“合同”;相似地,对于合同已签订这个畛域事件,是因为“合同”这个名词性概念的状态变动所导致的。
- 产出畛域模型
四色建模
对于四色建模的概念咱们可与追溯到 90 年代,是被宽泛应用的一种系统分析办法。四色建模的目标是要对指标业务零碎进行剖析并通过不同的色彩标示出人,事,物,角色,通过四色建模失去四色原型图,每个原型图有属性和连贯(关联与依赖等关系)两个局部组成。
那四色原型具体是哪四色呢?一起来看看
- 时标原型(Moment-Interval Archetype,简称 MI)
- 示意事物在某个时刻或某一段时间内产生的,如销售订单、收款记录等,应用浅红色示意。
- PPT 原型(Part-Place-Thing Archetype,人 / 事 / 物原型,简称 PPT)
- 示意参加表演不同角色的人或事物,如商品、账户、店铺等,应用浅绿色示意。
- 角色原型(Role Archetype,简称 ROLE)
- 形象了一种参加形式,由人或组织机构、地点或物品来承当,如客户、商家、财务组织等,应用浅黄色示意。
- 形容原型(Description Archetype,简称 DESC)
- 对上述色彩示意的内容进行解释,用于分类或者形容建模过程中产生的数据,事件,或者流动,应用浅蓝色示意。
用一句话来概括四色原型就是:一个什么样的人或物品以某种角色在某个时刻或某段时间内参加某个流动。其中“什么样的”就是 DESC,“人或物品”就是 PPT,”角色”就是 ROLE, 而“某个时刻或某个时间段内的某个流动”就是 MI。
接下来应用四色建模法来剖析畛域模型,总共分为四大步:
- 建设时标原型:寻找须要追溯的事件,依据追溯事件寻找脚印
- 建设 PPT 原型:丰盛模型,寻找时标原型四周的人 / 事 / 物,使它能够更好地形容业务概念
- 建设角色原型:进一步从中形象出能够参加到不同流程中去的角色
- 建设形容原型:把一些信息用形容对象补足
案例:商家征询
产品截图
梳理征询业务时序,任何的业务事件都会以某种数据的模式留下脚印。咱们对于事件的追溯能够通过对数据的追溯来实现,当咱们把这些数据的脚印依照工夫顺序排列起来,就能够清晰的揣测出过往的一段时间内产生的事件。
通过对业务的梳理能够产出了四色原型图的要害业务时刻,如上面表格
通过下面的表格大略晓得用户在 IM 利用中的要害业务时刻和对象
寻找要害业务时刻对象四周的人、事、物对象
从人, 事, 物中形象出角色
把一些形容信息用对象补足
产出畛域模型
限界笔纸法
限界笔纸法起源于 thoughtworks,由 thoughtworks 大佬提出的基于四色建模的改良办法。在“四色建模法”的“时标对象”的根底上确定 ” 限界上下文”与“汇集”的概念,再应用“纸和笔来治理”的办法,力求在建模过程中实现“分而治之”,加强数据的完整性,并防止适度设计。
建模步骤
- 依据“业务产生时刻”的价值辨认外围畛域 (core domain)
- 确定外围畛域之间的依赖关系
- 用纸和笔画表格并写实例(这里的实例能够是业务用例,用户故事,或者业务产生时刻)
- 确定“聚合根(AGGREGATE ROOT)”
- 以“人以群分”的准则抽取新的“聚合”
剖析模式
学会了下面的建模办法就有能力应答开发中等难度的零碎了。不过,如果遇到更简单的业务畛域,还须要更深刻的建模技能。《剖析模式》是 Martin Fowler 写的一本领域建模的专著。讲述各种剖析模式和辅助模式,专一于面向对象分析与设计的后果——模型自身,给出了来自金融贸易、测量、财务以及组织关系等多个畛域内的一系列模式。书中每个模式都蕴含了设计背地的原理、应用的规定以及实现的技巧,给出的例子蕴含了有用模型的细节,并介绍了用于进步剖析、建模和实现的重用技巧。钻研不深感趣味的能够看下。
代码建模
通过畛域模型的剖析后,面向对象曾经初具雏形,但畛域类并不能领导咱们进行编码工作,因为畛域类只是从用例模型中提炼进去的反映业务畛域的概念,并不是真正意义上的软件类,咱们要须要在进一步,实现畛域类到软件类的转换,这就是代码建模阶段的次要工作。那么具体如何做的
- 第一步:实现畛域类到代码类的映射
1. 类:畛域模型中的类间接映射成代码里的类
2. 属性:畛域模型类的属性间接映射成代码类里的属性
3. 动作:畛域模型类的动作间接映射成代码类里的办法
4. 状态机:畛域模型里的状态映射为类的状态机
5. 协作关系:用 UML 的类关系图从新刻画协作关系
以下面的一个畛域模型为例
- 第二步:利用设计准则和设计模式。实现了第一步,类就进去了,属性和办法也有了,是不是就完结了呢,如果依照设计准则的衡量标准,会发现第一步只是最根本的要求,而不是一个好的设计。还以 ” 用户购买商品 ” 案例为例,领取的形式分为支付宝、微信、银行卡,使用设计模式后,代码模型变成如下:
数据建模
数据模型推导的起源是畛域模型。个别准则,畛域模型中的实体映射为数据库中的表;畛域模型中的属性,映射成表中的字段,同时还要依据需要补充更多的字段。模型中的一个一对多关联,能够映射成一个外键字段,以及一个外键束缚。但个别不会真的建设外键束缚,而外键的逻辑关系还是存在的。能够用虚线箭头示意这种逻辑上的外键关系,称为虚构外键。对于多对多关联,必须减少一个关联表,其中包含了两个实体表各自的主键。另外,关联上的多重性决定了外键字段的非空束缚。
怎么判断模型好不好
- 畛域模型是生存中模型的映射。在几十年前,咱们没有计算机,然而咱们依然能够通过白纸黑字的形式实现咱们的业务。换句话说,咱们的业务零碎只是把一个纸质的单据变成了电脑里存在数据库里的货色。也就是说,咱们的模型,肯定是在生活中有理论的对应的单据,而且名字也应该是统一的。千万不要臆造概念。
- 畛域模型不是 DB 模型。畛域模型不是 DB 模型,一个畛域对象能够有多种形式映射到数据库,然而咱们聊畛域模型的时候,肯定不是聊 DB 模型,重要的肯定是形容分明业务概念。在做 ORM 的时候,如果有继承关系须要的实现的时候,咱们再思考是单表继承(Single Table Inheritance)还是实体表(Concrete Table Inheritance)等模式。
- 畛域模型的关系肯定是稳固的。当接到一个新的需要时,如果发现模型的关系不匹配了,那阐明之前的模型设计的必定存在问题,好的模型实体和实体之间的关系肯定是稳固的,只会新增不会对原有关系进行扭转。
畛域模型为什么要始终继续迭代
要在 ” 变动的事实世界中寻找不变性 ”,心愿寻找到一个稳固的畛域模型,让零碎流程能够灵便扭转,模型不怎么变,但在理论中却很难完满的做到,这是为什么呢?(备注:这里的迭代不是指对原有模型关系的重构,而是对模型新关系的降级)
- 意识问题。在用户、产品人员、经营人员眼中,沟通的语音是 ” 流程 ” 而不是 ” 模型 ”。开发人员在与他们的沟通过程中,缓缓就造成了以 ” 流程 ” 为主导,而不是以 ” 模型 ” 为主导的思维形式。这使得整个开发过程是 ” 流程驱动 ”,而不是 ” 畛域驱动 ”。大家在探讨业务与零碎解决方案的时候,大部分工夫都花在了业务流程、业务规定上,而不是粗浅开掘流程背地的不变因素。
- 事实世界的复杂性。业务也就是咱们的事实世界,灰度的、不置可否的货色,比计算机的世界多得多,变动也多得多。很难确定有哪些货色是不怎么变的,什么货色是容易变的,而这恰好是做建模的前提条件。
- 迭代速度。在巩固的模型,也不可能变化无穷,毕竟事实世界始终在变。当事实世界变动到模型不能撑持的时候,要能马上批改模型才行。但理论状况是,因为开发效率的起因,工期赶不上,而后就会在旧的模型上进行打补丁,补丁一个接着一个打,最初整个零碎臃肿不堪,开发效率进一步升高,如此恶性循环。
- 火候的把握。畛域模型是要对事实世界建模,既要去寻找不变性,又要为可能变动的中央留出扩展性。什么中央是不变的,要作为根底;什么中央是易变的,要留出扩展性,这其中并没有一个规范准则。另外,各家公司的业务规模、速度不一样,团队施行能力也不一样。所以在实践中,要么会 ” 不足设计 ”,要么会 ” 适度设计 ”。对火候的把握,须要有悟性。只有重复思考,重复颠覆本人之前的想法,再重建新的想法,能力在实践中一直找到畛域模型、业务倒退速度、技术团队能力之间的 ” 最佳平衡点 ”。
背地须要修炼的思维
下面讲的这些都是术的体现,是借假修真,只有 ” 真 ” 才是咱们修炼的道,也就是做事的思维,下图列举一些,欢送感兴趣的多交换。
作者 | 修冶
点击立刻收费试用云产品 开启云上实际之旅!
原文链接
本文为阿里云原创内容,未经容许不得转载。