美文网首页
浅谈学习业务系统建模理论的三重境界

浅谈学习业务系统建模理论的三重境界

作者: 郑渊 | 来源:发表于2022-11-13 17:49 被阅读0次

写在前面

市面上介绍业务系统建模的资料有很多,尤其是在领取驱动设计(Domain Driven Design, DDD)这套方法上不少同行都有对其进行讲解。所以,笔者这里不会重复的介绍DDD中那些晦涩难懂的建模概念,也不是DDD建模的狂热分子,也不迷信和盲从各种软件工程论,也不会“造个轮子”为了说明一些东西去提出新概念,更不会去推翻某些已存在的“轮子”。

在日常工作和交流中看到了大家学习建模的很多困惑,比如概念多且难懂,入门门槛高等,还有不少同行陷入在DDD中不能自拔,这些困惑我曾经也有过,如果行业有成熟的方案解决这类困惑,我这里也不想多余的表达。所以,基于理论和立足现实,分享下“如何学习建模”的一些浅薄的总结,帮助大家少走弯路,快速入门和解决实际问题。

简单谈下RUP

回顾我们的软件研发过程,以比较经典的RUP模型为例。这里谈下RUP是为了让大家对软件开发的过程有个全面的了解,为后续介绍各种建模方法和误区打下一个基础。

如下图1所示,一个软件研发的的流程可以分为很多阶段和步骤,一般在实际应用过程中,会根据项目规模和复杂度对RUP进行适当的简化。软件开发过程存在的本质是为了解决工程质量和效率的问题,每个流程都扮演着不可或缺的角色。我们工作中接触到的“研发效能”相关工作,如编写可读性代码,代码规范,单元测试覆盖率,自动化测试,持续集成和部署等是属于后置流程,而对于前置的流程在日常工作中关注的不太多。而初期前置的分析和设计工作恰恰是决定我们软件架构质量的关键因素,因为后期建设再牛逼的工具也解决不了初期设计上的缺陷。接下来介绍的业务系统建模的工作主要集中在“Requirements和Analysis&Design”这两个workflows中。

图1 RUP开发模型

并非只有微服务才需要建模

几年前很少有人提到建模,大家眼球都围着大数据,容器,微服务框架,云计算,机器学习等热门领域,当时学的东西不跟这些领域沾边都显得不够时尚。当发展到微服务后期,聊到微服务如何划分的时候,大家突然发现DDD是个好东西,社区也有不少的相关文章和分享。

其实,单体应用同样也需要进行建模和合理的模块划分。从图1RUP模型可知,单体和微服务只是在后续的实施和部署环节,所以不论你是单体还是微服务,前置的业务建模工作是绕不开的。

市面上有哪些建模方法

看软件建模理论的发展史,在1990年代中期之前就开始讨论着一些面向对象分析和设计的方法,随着多年的总结和演进,诞生了一些系统性的建模方法,如,领域驱动设计,用例驱动设计和属性驱动设计等,同时还有一套UML来表达我们的建模思想。各类建模方法对应的常见书籍如下图所示:

图2 

从社区分享和市面上的书籍来看,近几年领域驱动设计的热度要略胜。虽说DDD被炒的火热,但它也并非唯一的建模方法,并且也不是一个易懂且适合入门的建模理论。这里不想像学院派那样咬文嚼字去批判哪个不好,哪个是权威,都是前辈们沉淀下来的理论总结,当然也有其与之对应的时代背景,我们只需专注于如何利用它解决我们实际问题即可。

学习现状

在各类建模理论中充斥着各种各样的名词,概念和术语,有时为了说明一些概念又会引入新的概念,把学习者弄的晕头转向的,比如:领域对象,领域模型,领域服务,限界上下文等等;而且同一个名词在不同的建模体系里面,表达的含义还不一样,比如,领域模型在《大象-Thinking in UML》【2】里面和DDD的相关代表作里面表示的含义就不同,具体可参考【1】中的P468页。

那些看似复杂的概念到底应该如何去理解,多套建模理论到底谁是对的,知晓概念后又如何落地等这一系列问题,进而就有人觉得建模好难,到底什么样的方法才是对的和合适的,到底应该如何去学习才便于吸收和理解。

回顾下笔者的学习路程,14年在老师傅的介绍下开始接触《实现领域驱动设计》【12】,当时也刚工作不久,有些概念看懂了,比如实体等,觉得收获很大,有些没太懂,整体看完后也不清楚面对业务需求如何去落地。之后又去查阅了市面上的其它书籍,其中印象比较深刻的是《大象-Thinking in UML》【2】,在此本书中,笔者开始对面向对象的本质和用例驱动的设计方法有了很深刻的认识,加上一些工程项目的积累,然后回过头再去看《实现领域驱动设计》【12】,才开始恍然大悟。

当然,工作多年的人来看《实现领域驱动设计》【12】,也许他们会津津乐道的拍着大腿说,相见恨晚,他们可能会比较容易理解,毕竟有着丰富的项目和研发经验作为铺垫。但是对着工作不久的同学来说,我想就算大腿拍肿了,估计也很难去消化。

故而,想写一篇文章总结下建模的学习经验,笔者认为学习业务建模需要经过三重境界。

第一重 看山是山

初入职场,对很多事情都是懵懵懂懂,经常看到各类技术分享和评审上呈现的各种模块和框线图。时常会问别人这类模块的职责究竟是如何划分的,一个较完整的系统设计我们该如何找到切入点去思考,我们又应该如何表达我们脑海中的那一幅幅设计蓝图?当我们有这些疑问的时候,不少人会推荐去学习下领域驱动设计,似乎大家对领域驱动设计这类建模方法总是有种信徒般的崇拜。

当初启DDD这本书时,你就会不假思索地以为”眼见为实“,认为书中阐述的概念和方法就是对的,且能够帮你解决实际工作中的一些困惑。但常常事与愿违,通过与周围人的交流以及自身经历,接触这本书一般会有几类感觉:(1) 书上介绍的东西都挺有道理的,但是不知道如何下手;(2)部分概念接触后还挺有启发的,感觉挺有用的,比如实体,领域对象等。然后在项目的过程中也会刻意的去套书上的一些概念和模板,整个过程下来有时会显得有些生硬,形似而神不似。也许还会披着DDD的皮,实际上还是在做面向过程和面向数据的系统设计。勤奋的同学会带着这些问题又去查阅各种资料,总是会不停的怀疑和自省,是不是哪里理解的不太对,看大家说出来都是一套一套的,名词概念满天飞,为什么到了自己身上就不知如何施展了。其实本质原因还是大家都停留在对一些建模名词概念的理解上,没有抓住建模背后的本质。

第二重 看山非山

到了这个阶段会比第一阶段的人更加进一步,当他们在第一阶段遇到问题时,好奇心不强的人可能就一直似是而非,懵懵懂懂的停留在初始阶段。好奇心强的人会去进一步探索,求知和求真。比如寻求高人指点,会买很多各种各样的建模书,看看别人是怎么理解这个事情的。有一天他会发现建模领域的新大陆,老生常谈的DDD并非银弹和真理。在新大陆上,同样会衍生出一些新的概念来解释何为建模,同时还会遇到之前接触过的名词和概念,如领域模型这个概念在不同书中都有提到,但含义是不同的。实体这个概念在不同的书中也都有提到,且阐述的概念是一致的。书读的越多,也许概念上的冲突和歧义也就越多,相似概念的理解也就越深刻,读完后也许原本清晰的思路仿佛都不知道该怎么办了,犹如走火入魔一般。犹如慕容复练武,啥门派的都练一遍,却每个门派的都蜻蜓点水。

第三重 看山还是山

到了这个阶段,有些同学就开始顿悟。通过理论的不断学习和实践的检验,开始返璞归真,去繁求简,原来建模的本质就是生活的映射,艺术来源于生活,又高于生活,建模又何尝不是门艺术呢。抓住这个核心要素,再去看那些看那些书本上的晦涩难懂的概念,无非都是一些如何更好的方法和招式罢了。也不用在意那一招一式是否舞的足够精准,无招胜有招,在通晓原理的基础上,大家可以自创招式,或者选择自己合适的招式和方法即可。

我们究竟该如何做?

是不是每个学习和掌握建模理论的同学都需要经过前面我阐述的重重难关呢?不一定,但是通过多年工作中同身边同事的交流,或多或少都会面临我前面提到的问题。所以,笔者从实用的角度出发,提取了建模领域的核心概念和常见问题,帮助更多的同学跨过建模理论学习的重重门槛,在理论的支撑和实践的检验下,设计和演进出更好的软件架构模型。当然,笔者的经验有限,不足之处还望指正。

充分理解何为面向对象

建议大家再翻阅各种建模书籍之前,先搞清楚何为面向对象?只有把这个本质弄清楚,才能为理解后续各种建模理论打下坚实的基础。之所以强调“理解面向对象”的重要性,是因为见到了太多挂着DDD的皮,各种建模思路完全是面向过程那一套;见到了太多因为数据模型长的类似,去倒推或者扭曲业务模型的定义。

关于“面向对象”的解释在《大象-Thinking in UML》【2】一书在P2-P9中讲的比较透彻和容易理解,我这里就不重复了。大概从三个层面总结下:

第一层,哲学层面,认知世界的角度,你把这个这个世界视为过程还是对象?这个世界的本质是由对象组成的,平时看上去毫不相干的独立对象在不同的规则下体现出不同的过程,然后这个过程便展现出了我们这个生动的世界。

第二层,软件世界是现实世界的投影,现实世界中的认知方法在软件世界中同样有用。而领域驱动设计和用例驱动设计等建模方法论则是从这个认知角度总结出来的分析方法。

第三层,建模的本质就是映射,如下图所示,现实世界由人,事,物和规则组成,对象世界里面也有与之对应的参与者,用例,实体和业务规则。进而,我们对象世界的建模工作只需要围绕着参与者,用例,实体和业务规则展开即可。

图3

参与者,用例,实体和业务规则核心要素在RUP中的建模过程如下,我们通过需求与用例分析找到人和事(参与者和用例),通过实体分析找到物(实体),通过动态模型(规则),来把我们的物(实体)链接起来,达成我们的目标(事)。

图4

需求与用例

什么是需求以及如何获取需求在很多书中已经介绍的比较详细了,而且没什么争议,这里不再赘述。我们重点看下比较有争议的地方——用例。不同的建模方法中对”用例“介绍的维度不一样,如下图所示:

图5

用例是捕获需求的一种方式。虽说不同的书中对用例的分类不同,但大体上主要可以分为“业务用例”和“系统用例”两类,这个基本上是可以达成共识。

不同的是相关的定义解释在不同的资料中呈现的不一样,到底谁是权威?

这里建议不要咬文嚼字的去争论谁是权威,作为工程师,从解决问题的实用角度出发,理解好业务用例和系统用例这两个概念就可以。

业务用例

业界对相关业务用例的相关定义详见上面的图5,单看业务用例的中文解释,发现不同的书中从字面意思上看,讲解的不太一样,这就会造成一些误解。中午博大精深,不通的字面表达会产生不同的理解,我们先看看英文参考材料【3】的定义,重点关注“make use of the business to get the result”这一句,理解完之后,再回看《软件方法(上):业务建模和需求》【1】中的解释,发现这两段中文解释表达的内在意思是一样的,一个从业务的角度描述,一个从组织的价值来描述,本质都是表达你的业务或者组织可以给用户or客户解决什么问题,满足什么诉求,带来什么价值。比如,医院这个组织提供的价值就是看病,直播业务可以满足用户看直播,打赏主播/送礼物等诉求。

图6 业务用例

所以,大家在理解“业务用例”这一概念的时候,建议大家去看英文的这段注解,掌握背后的本质后,理解再去看一些中文的解释,就会容易许多。

系统用例

业界对相关系统用例的相关定义详见上面的表2,同业务用例一样,单看中文定义,《UML和模式应用》【4】和《Thinking in UML》【2】中的定义比较相近,也容易理解,而《软件方法(上):业务建模和需求》一书中的定义就略微显得抽象了,抽象点在于“涉众可以接受的价值”。然后再看英文定义,重点关注“make use of the system to get the result they want”,就表达的比较直白。你可以把这段理解为功能性或行为性需求,这是从系统使用者(可能是人,可能是其它系统)的需求出发来解释的。而软件方法一书则是从涉众可以接受的系统价值出发的,系统价值的本质就是能满足系统使用者的需求。所以,这么一理解不同书中对统一概念解释的本质是一样的,只是解释的角度不同而已,但也是在通晓原理的前提下去理解,不然就容易被一类解释带偏,陷入字里行间的争吵中。

常见困惑

业务用例和系统用例的关系

首先谈业务和系统之间的关系,系统是用来支撑业务策略,业务策略的落地不一定全依赖于系统。所以说是先有业务,后有系统。我们是先有业务用例,然后才会有系统用例。系统用例是从业务用例推演出来的。具体的推演过程如下图所示,为了表示更加的清晰,我们以常见直播业务的礼物场景为例来分析。

图7 业务用例和系统用例

为什么这里要重点介绍业务用例和系统用例

一些计算机类书中如果没有明确说明系统用例还是业务用例,一般情况下这类用例都是代表的系统用例,因为它是直接跟计算机系统的功能性需求强相关的。但这样容易把读者引入到忽略业务用例在建模过程中的重要性的这个误区。对于小系统还好,一旦遇到一个比较大的业务涉及到多个功能和多个子系统,如果我们一开始就从系统用例的视角来分析,会发现要分析的系统用例太多,分析不过来,而且层次和粒度不一致,很难系统性的去抽象,这也是我这里强调在建模初期业务用例重要性的原因。

从业务用例到系统用例这种建模路线,本质上是一种从上到下思考,分层设计,分而治之的分析思路。它是分解复杂问题和后续实体抽象的基础。

建模理论中的用例和UML中的用例图有什么联系

统一建模语言UML中的用例图来帮助我们落地用例建模理论中的用例概念,用图形化的方式表达出来。在领域驱动设计中也是同理,里面的事件风暴当中的领域事件也可以用UML中的用例图来表达,UML中的用例图是一种表现形式。

这里的用例和领域驱动中的事件风暴是不是一回事

有两个概念有些相似,他们都用来分析需求,且都可以用UML的用例图来表达。但是领域驱动中的事件风暴倡导的是首先提取领域中发生的事件,从非常细节的动作入手来分析需求【6】。这种分析思路会显得很琐碎,没有去区分事件的粒度,当你面对一个比较庞大的系统时,功能众多,你面临的事件也是非常多的,这时分析和抽象起来就会显得非常吃力。

而这里我们强调业务用例和系统用例。先分析业务用例,可以在初期把有限的精力专注到用户和客户的核心诉求上,再通过一系列的拆分手段去分析系统用例。

实体

不同建模方法和不同书中都有提到“实体”这个概念,如下图8所示:

图8

有些定义描述看着比较类似,有些定义描述看着表达的不是一个事情。领域驱动的相关书籍从唯一标识,生命周期的角度来介绍实体,说实话这类由内而外的介绍,理解起来是有些抽象的。而在用例驱动方向,他把实体介绍成事物or系统。在现实生活中我们把实体描述为“事物”,映射到软件世界中实体可以表达为软件对象或者系统,当然也有可能是一个类。这种从外向内的介绍方法是比较容易吸收的。

既然是事物,那必然有描述事物的唯一性,也就是唯一标识,当然这个标识可能是由事物的本身的属性组合而成,也有可能是为其分配的一个唯一ID。

为了让大家理解的再透彻一些,实体从字面意思上看,意思是客观存在并可相互区别的事物【5】。而这个事物是完成这件事情所需要的客观物体。比如你要去给女孩儿送礼物,完成这件事情需要钱,商品等物体。而这些物体有它的唯一标识和对应的行为方法。

那么我们从这个角度来解释,是不是就更容易理解了。了解本质后,再回头看各种书中和各种流派中的定义,就很容易理解他们表达的意思的相似的。

常见困惑

为什么要在建模阶段引入“实体”概念呢?

不论是我前面介绍的业务/系统用例,还是DDD里面提到的领域事件。我们要去完成这个用例或者事件,总是要靠不可或缺的实体/事物。而这些实体/事务,才是我们建模的关键。在现实世界中,它是一个汽车,菜刀,钱等等一些实实在在存在的物品,在软件世界中它可能就对应着一个软件对象,一个系统,一个组件,一个包或者一个类。

如何寻找实体/事物?

我们还是以直播业务的送礼物场景为例,如下图所示,人习惯性对看着见摸者着的东西理解起来都比较容易,对一些虚拟的场景,可能就会摸不着头脑了。前文有提到过,建模的本质是映射,我们可以去生活中寻找灵感。比如你送一个礼物给一个妹子,看需要哪些事物?钱,物品,贺卡,快递等,如果是自己送可能还有汽车,如果下雨可能还需要一把伞。梳理出这些事物后,从中找出“关键事物”—缺少这个事物后,目标则达不成。我们通过“关键事物”缩小建模初期事物分析的范围,把有限的精力放到核心事物的分析上。然后,我们再将这些事物根据需求文档上的业务规则和定义,近似的映射到软件世界中,形成对象世界中的业务实体关系模型。

图9

从生活作为切入点,寻找灵感的分析方法是比较容易打开思路和吸收的。同时还需基于业务规则和其它分析方法,来提取软件对象世界中需要用到的事物。这些方法在不同的书中有不同的介绍,在实际的项目中可以综合运用,如下图所示:

图10

动态模型

之前介绍的用例和实体都是属于静态模型,实体/事物本身是静态的,我们需要通过一些协作和规则将之前分析的静态模型组织起来,来完成我们的用例,这个过程我们称为动态建模的过程。这里提到的静态模型和动态模型也不是什么新的且难以理解的概念,所以这里我就引入进来了。而动态模型的具体的表现形式则需要借助UML来表达,如顺序图/时序图,活动图,协作图或者通信图。我们还是以图9中介绍的礼物场景的业务实体静态模型为例,通过送礼物的规则,我们可以得到如下用序列图表达的动态模型。

图11

有些书中会把建模方法和UML结合在一起讲,尤其是在用例驱动的建模书中,容易让人误以为UML就是用例驱动设计。实则UML只是一种建模语言,而常用的建模思想则有用例驱动设计和领取驱动设计等。

但是在部分领域驱动设计的书中很少去系统引入UML相关概念,同样会造成看完DDD后不清楚如何落地和表达。当然,我们也不用死磕UML,就好像作为日常交流,我们只需要掌握常用汉字即可,学会用20%的UML语言表达80%的架构思想。

图12

业务架构模型

在一些常见的业务建模书中很少有提到业务架构模型的概念,但是这里还是有必要讲下,不然缺乏一个全局的视角来俯览我们实体之间的依赖关系,以及如何用我们抽象出来的实体表达我们的业务架构。目前业务架构模型的构建可以借鉴一些经典的架构模式,架构模式是对给定上下文的软件架构中常见问题的一种通用的可复用的解决方案,同大家熟悉的设计模式类似,设计模式是面向代码层面的,而架构模式是面向架构层面的经典解决方案。

常见的架构模式有哪些建议大家可以参考《Software Architecture Patterns》一书,不同的架构模型有不同的适用场景。其中对于web类的业务来说,常用的就是经典的分层架构。根据动态模型所描述的各个实体之间的依赖关系以及实体本身的职责定位,我们可以用分层的方式来表达礼物业务涉及到的业务架构。还是以直播业务的礼物场景为例,如下图所示。

图13

想必大家对这类图并不陌生,一个架构图内部包含很多子模块,而子模块如何划分和定义,是怎样的思考过程产生了这些子模块,则是我前面介绍的那些常见的分析方法。

建模思路小结

不同的建模书籍中提到的名词概念很多,每个概念单独拿出来讲都可以写一个章节或者写成一本书。建议一开始不要陷入各种复杂概念的理解和纠结上,先去充分的理解何为面向对象,建模的本质是映射,再去回看各种建模书中阐述再多的道法术,因为这些招式都是围绕寻找软件对象世界中的人,事,物和规则展开的。

当你面对一些虚拟场景,如果不知道如何去分析实体模型,要学会从生活中寻找灵感,软件来源于生活,更高于生活。建模的概念很多,个人认为通过用例分析,实体分析,动态建模三个建模领域的核心概念以及最后提到的业务架构模型,基本上就可以应对大部分业务建模场景。                             

图 14

总结

写完这篇文章,虽然一些概念跟用例驱动设计的理念有关,但并不是为了去推崇某一个方法论,其实在领域驱动设计里面提到的概念,也非常的有价值,比如统一语言的概念有利于我们在需求分析和架构设计的时候,把名词概念对齐,提高讨论的的效率;比如上下文映射的思想也有利于我们在代码实现中构建我们的防腐层;比如CQRS概念能让我们在不破坏原有的领域模型的架构设计上,有效的把面向数据模型的多条件聚合查询需求和面向业务模型的操作需求进行隔离等等;比如DDD中对实体,值对象和聚合根的介绍,让我对于业务场景中什么时候作为属性来分析,什么时候作为单独的实体来分析,什么时候作为聚合根存在,有了更加深刻的认知。

在毛泽东的思想中有一个最突出的根本点,就是首先要把握住事物的“本原”或“大本大原”。它的意思,是在面对万千事物时,要从大处着眼,首先抓住它的根本。把根本抓住了,其他枝节问题才能迎刃而解。学习和运用建模也是同样的道理。

天下武功出自少林,但随着演进和发展,形成了各种流派,各家都有各家所长,但都是在通晓得了原理上而得来的,大家选择自己合适的方法即可,我分享的不是规范不是招式,而是背后的基本道理!

参考资料

【1】《软件方法(上):业务建模和需求》,出版时间:2018

【2】《大象-Thinking in UML》(第二版),出版时间:2012

【3】《Business vs. System Use Cases》,Author: Martin Langlands and Charles Edwards,Date: 22 Feb 2009

【4】《UML和模式应用(原书第三版)》,出版时间:2006

【5】https://baike.baidu.com/item/%E5%AE%9E%E4%BD%93/422661?fr=aladdin

【6】《复杂软件设计之道:领域驱动设计全面解析与实战》,出版时间:2020

【7】《UML用例驱动对象建模:一种实践方法》,出版时间:2005

【8】《领域驱动设计(Thoughtworks洞见)》,出版时间:2020

【9】《领域驱动设计精粹》,中文译-出版时间:2018

【10】《领域驱动设计 软件核心复杂性应对之道》,中文译-出版时间:2010

【11】《解构领域驱动设计》,出版时间:2021

【12】《实现领域驱动设计》,中文译,出版时间:2014

【13】《软件架构设计实用方法及实践》,中文译,出版时间:2017

相关文章

  • 浅谈学习业务系统建模理论的三重境界

    写在前面 市面上介绍业务系统建模的资料有很多,尤其是在领取驱动设计(Domain Driven Design, D...

  • 三境界-关于读书

    王国维在《人间词话》里的三重境界理论,即可放之于人生,又可放之于读书,读书的三重境界: ‘昨夜西风凋碧树,独上高楼...

  • 《中学语文教学》2019年第四期发表的文章

    浅谈《祝福》里的三重世界

  • 杨钧淇讲解人生三重境界

    杨钧淇讲解人生三重境界,人生360体系认为,人生境界很有意思,值得弘扬传播。 人生有三重境界,这三重境界可以用一段...

  • 真正厉害的人是因为ta知道如何成长

    ////三重境界////人的成长分为三重境界。宋代禅宗大师青原行思提出参禅的三重境界与人的成长高度一致:参禅之初,...

  • 笔记

    1、学习三重境界:学知识和理论(默而识之),知识改变生活(学而不厌),内化(诲人不倦)----先消化再转化后进化、...

  • 2020-03-26人生三重境

    晨读 池莉: 人生有三重境界 人生有三重境界,这三重境界可以用一段充满禅机的语言来说明,这段语言便是:看山是山,看...

  • 读《理想课堂的三重境界》有感(三)

    理想课堂的三重境界:第一重境界:落实有效教学框架;第二重境界:发掘知识的内在魅力;第三重境界:知识、生活与...

  • 【百日行动】

    读《跃迁》30页 “勤奋的三重境界” 第一重境界:很努力 第二重境界:方法论勤奋 第三重境界:更少目标,战略勤奋 ...

  • 用例帮你发现价值,建模带来竞争优势

    刚开始读这本书时,我很惊讶,程序员都已经在学习业务建模了,而我作为业务分析人员如果都不懂业务建模,真是自行惭秽。 ...

网友评论

      本文标题:浅谈学习业务系统建模理论的三重境界

      本文链接:https://www.haomeiwen.com/subject/gbxkxdtx.html