Appearance
第3章 统一建模语言UML
1.3 统一建模语言 UML
1.3.1 UML 的历史和现状
UML(Unified Modeling Language,统一建模语言)是由 OMG (对象管理组织)维护的一种软件建模表示法标准。
在 1.2 中,我们阐述了 A→B→C→D 的推导是不可避免的,但具 体如何推导,有各种不同的做法,这些做法可以称为“方法”。甚至只 要愿意,每个人都可以创造自己的“方法” ,无非是有的正确,有的错 误,有的高效,有的低效。有一些“方法”被成体系地归纳出来,并向 业界推广,这些可以称为“方法学”。
最开始的软件开发方法学重点关注的是 D 部分,即所谓的“程序 设计方法学”。后来,才逐渐在方法学中加入前面的部分,大致的添加 顺序和推导的顺序刚好相反,→C→B→A。其中的很多概念借用了其他 学科的术语。像“流程建模”、“需求”等术语在计算机出现之前就已经 存在,而且含义和今天软件开发中使用时的含义差不多。
本书不想花很多篇幅来回顾这些方法学中的概念的历史,感兴趣的 读者可自行搜索相关论文,例如 Kolligs 等人写的“The Origins of Requirements”[Kolligs 2021]。
20 世纪 60-80 年代,有名的软件方法方法学有:功能分解、数据 流、E-R(实体-关系)等。
进入 20 世纪 90 年代,OOAD(面向对象分析设计)方法学开始 受到青睐,许多方法学家纷纷提出了自己的 OOAD 方法学。流行度比 较高的方法学有 Booch、Shlaer/Mellor、Wirfs-Brock 责任驱动设计、 Coad/Yourdon、Rumbaugh OMT 和 Jacobson OOSE。其中, Jacobson 的方法学添加了用例、业务工人、业务实体等概念,为 OOAD 方法学扩展了业务建模和需求部分。
这个百花齐放的局面带来了一个问题:各个方法学有自己的一套概 念、定义和标记符号。
例如现在 UML 中的操作(Operation),在不同方法学各有叫法, 这些叫法有:责任(Responsibility)、服务(Service)、方法(Method)、 成员函数(Member Function)……
同一个类图,不同方法学也有各自的符号表示。 在图中,我们可以看到,三角形符号在 OMT 方法学中表示泛化,在 Coad/Yourdon 方法学中却表示关联,Coad/Yourdon 方法学中泛化 用的是类似铃铛的形状。
类似这样的差异造成了混乱,使开发人员无从选择,也妨碍了方法 学的推广。
1994 年,两位已经在 Rational 公司工作的方法学家 James Rumbaugh 和 Grady Booch 开始合并 OMT 和 Booch 方法。随后, Ivar Jacobson 带着他的 OOSE 方法学加入了 Rational 公司,一同参 与合并工作。这项工作造成了很大的冲击,因为在此之前,各种方法学 的拥护者觉得没有必要放弃自己已经采用的表示法来接受统一的表示 法。
Rational 公 司的 这 三位 方 法学 家 被大 家 称为 “ 三友 ”( three amigo)。1996 年,三友开始与 James Odell、Peter Coad、David Harel 等来自其他公司的方法学家合作,吸纳他们的成果精华。1997 年 9 月,所有建议被合并成一套建议书提交给 OMG。1997 年 11 月, OMG 全体成员一致通过 UML,并接纳为标准。
从 2005 年起,UML 被 ISO 接纳为标准。ISO/IEC 19501 相当于 UML 1.4.2,ISO/IEC 19505 相当于 UML 2.1.2。2012 年,ISO 继续 接 纳 UML 2.4.1 为 ISO/IEC 19505-1:2012 和 ISO/IEC 19505-2:2012,接纳 OCL 2.3.1 为 ISO/IEC 19507:2012。
2011 年 , 中 华 人 民 共 和 国 也 发 布 了 统 一 建 模 语 言 国 家 标 准 GB/T28174。
UML 的最新版本是 OMG 于 2017 年 12 月通过的 UML 2.5.1, 相关网址: https://www.omg.org/spec/UML/。
OMG 还和各种行业标准组织如 DMTF、HL7 等结盟,用 UML 表 达行业标准。
UML 诞生已经超过 25 年,在软件开发表示法标准上已经获得了 胜利。随便打开一本现在出版的软件开发书,里面如果提到建模,使用 的标准符号基本都是 UML。
另外,以 UML 为契机,掀起了一股普及软件工程的热潮,在 UML 出现后的几年,不但有关建模的新书数量暴增,包括 CMM/CMMI、 敏捷过程等软件过程改进书籍数量也出现了大幅度增长。制定 UML 标 准的角色(OMG) 、根据标准制作建模工具的角色(UML 工具厂商) 使用 UML 工具开发软件的角色(开发人员)这三种角色的剥离,也导 致建模工具的数量和种类出现了爆炸性的增长。而之前的数据流等方法 从来没有像面向对象分析设计方法一样,出现 UML 这样的统一表示法, 从而带动大量书籍和工具的产生。
最开始一批 UML 书籍,基本上由方法学家所写。最近几年,以 “UML”为题的新书大多为高校教材或普及性教材。这并不是说 UML 已经不重要,而是没有必要再去强调,焦点不再是“要不要 UML”,而 是要不要建模、如何建模。
根据 UMLChina 的统计,UML 相关工具最多时达 168 种。经过 市场的洗礼,现在还在更新的还有几十种,有商业工具,也有免费或开 源工具。隔一段时间,UMLChina 会整理最近的 UML 工具更新情况, 发布在 http://www.umlchina.com/url/tools.html。
1.3.2 使用 UML(或某种标准建模语言)的理由
在开发团队中,不乏刻意排斥 UML 的人。这些人如果只是不使用 UML,改为使用其他标准的图形表示法(如 BPMN),那倒没有什么好 说的——但仔细观察可以发现,绝大多数情况下并非如此,这些人要 么使用自编的“图形表示法”,要么使用文本,甚至有的人只强调“口 头交流” 。 当然,通过 UML、自编图形、文本、语音等形式都可以交流软件 开发中的各种逻辑,但背后的效率是不一样的。
1.3.2.1 听觉 vs. 视觉
回忆一下我们在学生时代做听力题和阅读理解题的过程,就可以体 会到,相对于听觉,视觉传递信息的效率更高,而且可以传递更复杂的 信息。正常情况下,把模型表达成视觉信息,不管是文本还是图形,比 起语音信息来说是更好的选择。非正常情况,视觉无法使用的时候,例 如开车或者累得眼睛睁不开,这时用语音来见缝插针,通过听觉利(zhà) 用(gān)建模人员的生产力,也不是不可以。
如果有人以“敏捷”为理由,特别推崇“口头交流”,排斥文档或 图形,很可能是遮羞布,背后的脓包是此人没有能力剖析复杂逻辑,试 图通过这种方式来遮掩。
有的开发团队动不动就开会,你一嘴我一嘴,场面看起来热热闹闹, 其实沟通的效果不好,更谈不上思考的深度和知识的沉淀。对比一下街 坊老大爷下象棋的热闹和职业棋手比赛时的沉静就知道了。
1.3.2.2 文本 vs. 图形
相对于只有自上而下顺序的文本(包括自然语言文本和编程语言文 本),能够朝四个方向扩展的平面图形(如果有三维模型就更好了)更 容易让建模人员看出领域概念之间的联系。例如,图 1-9 和图 1-10 的 内容,如果没有图形的帮助,通过文本一行一行地构造和阅读模型,人 脑的负担非常重。
text
图 1-9
@startuml
!theme plain
hide empty members
skinparam linetype ortho
class 员工 {
-姓名
-电话
-入职日期
-上级
-下级
}
class 客户 {
-名称
-联系人
-联系电话
-开户银行
-开户账号
}
class 订单 {
-订单号
-合计金额
-支付方式
-客户
-员工
-付款状态
}
class 支付方式 {
-名称
}
class 产品 {
-名称
-单价
-库存数量
-上架状态
-分类
-品牌
-规格
}
class 分类 {
-名称
-描述
}
class 品牌 {
-名称
-描述
}
class 规格 {
-名称
-描述
}
class 促销活动 {
-名称
-开始时间
-结束时间
-折扣率
-适用商品
}
class 优惠券 {
-名称
-面额
-使用条件
-有效期限
-客户
}
class 价格 {
-名称
-数值
-产品
-生效时间
}
class 价格因子 {
-名称
-类型
-值
}
class 价格因子模型 {
-名称
-描述
-版本
-启用状态
-价格因子
}
class 制作流程 {
-名称
-步骤
-耗时
-负责人
}
class 非标准定制商品 {
-名称
-材质
-工艺要求
-制作流程
-主材成本
-辅料成本
-人工成本
}
class 门店 {
-名称
-地址
-联系电话
-营业时间
-负责人
-所属区域
}
class 区域 {
-名称
-上级区域
-下级区域
}
class 门店管理 {
-名称
-门店
-管理员
-操作记录
}
class 营业员 {
-姓名
-手机号
-所属门店
-岗位
-权限
}
class 账户 {
-用户名
-密码
-角色
-状态
-创建时间
}
class 订单项 {
-数量
-单价
-总价
-产品
-订单
-备注
}
class 操作日志 {
-操作人
-操作时间
-操作内容
-IP地址
-结果
}
class 数据字典 {
-名称
-描述
-数据类型
-长度
-默认值
-是否必填
}
class 项目 {
-名称
-开始时间
-结束时间
-负责人
-状态
-预算
}
class 管理关系 {
-管理对象
-被管理对象
-关系类型
-创建时间
}
' 关联关系
员工 "1" -- "0..*" 下级 : 上级
员工 "1" -- "0..*" 上级 : 下级
员工 "1" -- "0..*" 订单 : 创建人
员工 "1" -- "0..*" 门店 : 所属门店
员工 "1" -- "0..*" 门店管理 : 管理员
客户 "1" -- "0..*" 订单 : 客户
客户 "1" -- "0..*" 优惠券 : 客户
订单 "1" -- "0..*" 订单项 : 包含
订单 "1" -- "1" 支付方式 : 使用
订单 "1" -- "1" 门店 : 所属门店
订单 "1" -- "0..*" 促销活动 : 参与
产品 "1" -- "0..*" 订单项 : 被订购
产品 "1" -- "1" 分类 : 属于
产品 "1" -- "1" 品牌 : 属于
产品 "1" -- "0..*" 规格 : 具有
产品 "1" -- "0..*" 价格 : 有价格
产品 "1" -- "0..*" 制作流程 : 使用流程
产品 "1" -- "0..*" 非标准定制商品 : 是定制品
分类 "1" -- "0..*" 产品 : 包含
品牌 "1" -- "0..*" 产品 : 包含
规格 "1" -- "0..*" 产品 : 包含
促销活动 "1" -- "0..*" 产品 : 适用于
促销活动 "1" -- "0..*" 优惠券 : 关联
优惠券 "1" -- "0..*" 订单 : 使用
价格 "1" -- "1" 产品 : 对应
价格 "1" -- "0..*" 价格因子 : 由因子决定
价格 "1" -- "1" 价格因子模型 : 使用模型
价格因子 "1" -- "0..*" 价格因子模型 : 属于
价格因子 "1" -- "0..*" 价格 : 影响
制作流程 "1" -- "0..*" 产品 : 应用于
制作流程 "1" -- "0..*" 非标准定制商品 : 应用于
非标准定制商品 "1" -- "0..*" 制作流程 : 使用流程
非标准定制商品 "1" -- "0..*" 产品 : 作为原料
门店 "1" -- "0..*" 营业员 : 包含
门店 "1" -- "1" 区域 : 所属区域
门店 "1" -- "0..*" 门店管理 : 被管理
区域 "1" -- "0..*" 区域 : 上级区域
区域 "1" -- "0..*" 区域 : 下级区域
门店管理 "1" -- "0..*" 门店 : 管理
门店管理 "1" -- "1" 员工 : 管理员
账户 "1" -- "0..*" 员工 : 对应
账户 "1" -- "0..*" 客户 : 对应
操作日志 "1" -- "1" 员工 : 操作人
数据字典 "1" -- "0..*" 项目 : 用于
数据字典 "1" -- "0..*" 管理关系 : 描述
项目 "1" -- "0..*" 员工 : 负责人
项目 "1" -- "0..*" 门店 : 涉及门店
管理关系 "1" -- "0..*" 员工 : 管理对象
管理关系 "1" -- "0..*" 门店 : 被管理对象
管理关系 "1" -- "0..*" 项目 : 关联项目
@enduml
说到这里,又不可避免地要提醒,故意选择文本的形式来表达领域 知识,有可能也是一种遮羞布。 可能会得到很多页文本——这就有了理由:因为工作量太大了,所以 很多地方无法做深入的思考,可以原谅!
1.3.2.3 自编图形 vs. 标准图形
事实上,纯口头交流甚至纯文本交流是很少见的。除非要交流的问 题极其简单或者其他同事对这样的人极其容忍,否则他至少也得随意画 几张“草图”来传达自己的意思——自编的图形才是比例最大的存在。
这样的人之所以用自编的图形,往往并不是因为他看出了 UML 有 哪些不足,然后用自己的表示法弥补了这些不足,而是要遮掩背后的一 些脓包。
脓包一:利益绑架
项目中,有人画了张自编的图形,然后往往会伴随这样的招呼,“来, 我给大家讲讲!”。这意味着项目要依赖于“我”头脑中的隐式知识— —要是“我”不给大家“讲讲”,大家就不理解“我”画的图的意思, 项目就玩不转了。于是,“我”在团队里的地位就提高了,大家得哄着 “我”捧着“我”,领导不敢轻易开掉“我”, “我”离职领导还要挽留。 这在有一定资历、但又不对项目的成败承担首要责任的“高手”身上表 现得更明显。
★花絮:开发人员让我看他的模型时,如果开口说“我先来给你讲 讲”,我都会拦住,“如果还需要你先讲讲,说明你所想的没有体现在 模型中”。
脓包二:遮羞
因为符号是“我”自创的,所以这个图的解释权归“我”所有。如 果有其他同事质疑图上什么地方画得不对, “我”就有了充分的躲闪空 间——“你理解错了,这个图形不是你以为的那个意思。你以为我画 的是鹿,其实这是马,在我的规范里面,马就是鹿的意思,鹿就是马的 意思”。
如果使用了标准的表示法,例如用 UML 画了一个状态机图,其他 人就有得说了,“好像手册上不是这样说的”,“我看那个书上不是这样 说的”,这不就尴尬了嘛。
自编图形未必是看起来十分简陋的白板草图,也有看起来比较精致 的。
其实,抛弃标准符号和建模工具带来的便利,用绘图工具或幻灯片 工具画出这样的图,所花费的时间往往还要更多。但是,有意思的是, 有的人画这样的图,还以“敏捷”为理由。
注意,上面说的只是“看起来比较精致”,其实内容还是很粗陋的, 仅仅是把一些动词、名词的罗列成一个个形状,各个形状之间的关系基 本没有,读者可以把图 1-11 和图 1-9、图 1-10 对比。
有心的读者可以观察近年来被吹捧为“革命性创造”的领域驱动设 计的文章,看看其中所画的图,看看会不会发现上面所批评的情况,简 单罗列,无一致性。
1.3.2.4 挑破乱七八糟图的脓包
我们甚至可以“抛开事实(具体领域知识)不谈”,仅从“一致性” 这一点入手,就可以挑破这种自编“乱七八糟图”的脓包。
自编“乱七八糟图”的画图者,很可能并没有归纳过各种形状的定 义,只是凭感觉随意使用,或者即使归纳了,也不会像标准语言这么严 谨,所以,大概率会产生“不一致”的问题。
我们就以图 1-11 为例。
图 1-11 中,同样被称为“平台”的东西,有着不同的形状和颜色, 如图 1-12。
我们再来看中间这些方框.
先看图 1-13 的最顶上 3 个方框,它们形状一样,长度一样,但有 的叫“层”,有的叫“模型”,有的叫“队列”,这些概念可不是一个级 别的。
(可能的辩解)也许在颜色中暗示?
再来看方框里的命名。最上面 4 行的命名,基本上都是“名词+动 词+名词”结构,例如“消费信贷+统一前置+层”、“额度+管控+模型”, 最下面 2 行的方框,命名是“名词+动词”结构,例如“消费业务+管 理” 、“流程+控制”。
(可能的辩解)你没脑子吗,自己脑补一个尾巴不行吗,“……模 型”、“……层”、“……功能”、“……队列”“……AI 赋能领域驱动设计革 命性创新微服务功能模块组件分布式大数据数智化平台”
还有,名称同样是“模型”,颜色也有多种……
读者可以尝试从“一致性”着手,看看身边的同事画的“乱七八糟 图”有没有这方面的问题。
可能有人会问:难道用 UML 来画就没有这个问题吗?
有的,例如,建模人员故意往用例的圈圈里乱填东西,有的填名词, 有的填动词,有的填形容词,但这是违反 UML 相关的规范或指南的, 其他人可以看出问题,批评和纠正。刚才说的情况是没有规范或规范模 糊,这两者是不一样的。
用法律类比:精确严谨的法律条文并不能保证没有人违法,但至少 大家有共识,什么是违法,什么不是。而另一种情况则可能是,孪生兄 弟张三和张四做了同样的事情,张三违法,张四不违法,理由?不知道。
1.3.2.5 基本共识上的沟通
表示法标准并不是随便哪个人拍脑袋定下来,然后毫无道理地强迫 大家接受。符号背后往往隐含着我们对某个学科的一些基本共识。
如图 1-14,最上一行的积分表示法“∫”,幼儿园小朋友也能画出 这样的形状,但其所代表的知识可能需要上到大学才能理解。如果要懂 得为什么是这样一个表示法,还需要了解数学史中莱布尼茨、傅立叶等 人的贡献。图 1-14 中间一行的五线谱小豆芽和横线,最下一行 UML 的小人圈圈和框框,也是如此。
这意味着,学习建模表示法标准并非硬生生把形状记住后照葫芦画 瓢就行,还要学习背后的一些建模知识。但是,开发团队成员咬咬牙, 花费一些精力跨过这个门槛是值得的,因为一旦有了基本共识,会大大 提高沟通的效率和深度。在严谨建模思维的追问之下,有意无意遮掩的 脓包也会被强制露出——这也是一些“高手”潜意识里不愿意直面 UML 的深层原因。
★花絮:面对一个棋局,下一步怎么走?在业余棋手看来到处都是 正确答案,在职业棋手眼里,值得讨论的选项只有两三种,因为职业棋 手针对一些东西形成了共识,大大减少了思考中的浪费。
★花絮:有的开发人员的“十年工作经验”实际上是“一年工作经 验用了十年”,一直在热热闹闹的民工层次徘徊,没有积累和成长。
不过要注意一点:使用 UML 沟通仅限于软件组织内部,UML 模 型不是用来和涉众沟通的!这个道理以及和涉众沟通的技能将在第 7 章详细叙述。
1.3.3 SysML
UML 的另一个成就,就是把“统一建模语言”扩展到了系统工程。 INCOSE(国际系统工程协会)和 OMG(对象管理组织)以 UML 为 基础,进行系统工程方面的扩展后推出了 SysML(Systems Modeling Language,系统建模语言),目的是和 UML 相似:为了统一系统工程 的建模语言。
UML 是信息系统的建模语言。 “信息系统”的意思是该系统只负责 处理信息:信息流进来,经过系统的处理,变成信息流出去,但是,信 息系统不能处理物质流和能量流——或者简单说就是能量流,因为物 质是能量表现形式之一。
SysML 可以建模处理能量(物质)流的非信息系统。将来能量(物 质)、信息进一步大一统,SysML 是可以取代 UML 的,但目前还不能。
关于系统工程、软件工程、SysML、UML 的区别,我用刘慈欣的 小说《流浪地球》举个例子。
太阳即将在 400 年内发生氦闪变成红巨星,人类社会怎么办?
众多科学家经过大量研究,得到一个解决方案:给地球装上发动机, 驱动地球飞向比邻星(夭寿啦!正好三体舰队迎面飞来,嘭!)。
小说《流浪地球》原文:
地球发动机安装在亚洲和美洲大陆上,因为只有这两个大陆完整坚 实的版块结构才能承受发动机对地球巨大的推力。地球发动机共有一万 二千台,分布在亚洲和美洲大陆的各个平原上。 ……
在六千米处,我们见到了进料口,一车车的大石块倒进那闪着幽幽 红光的大洞中,一点声音都没传出来。
……
“重元素聚变是一门很深的学问,现在给你们还讲不明白。你们只 需要知道,地球发动机是人类建造的力量最大的机器,比如我们所在在 华北 794 号,全功率运行时能向大地产生一百五十亿吨的推力。 ”
“地球发动机”是一个巨大的系统,横跨多个学科,能源、材料、 建筑、物流、人员管理……。
其中用来描述和处理信息的信息系统可能只占其中的一小部分, UML 不适合描述“地球发动机”,SysML 可以。
通过 SysML 建模,不断把“地球发动机”分解成各个 Block,Block 又分为小 Block,可能会得到其中一个 Block 叫“发动机中控系统”, 这是一个信息系统。该系统其中一个功能可能是:根据接收到的测量参 数值(可能有上万个) ,计算地球发动机下一步的最佳行动。
听起来 SysML 描述的系统比 UML 描述的信息系统大,是不是意 味着 SysML 建模的难度更高? 目前来说并非如此。目前使用 SysML 建模时,更多的是“描述”, 例如描述“地球发动机”的各个部件及部件之间的关系。至 于为什么地球发动机的部件和关系是这样的,这可能是其他各个学科的 专家的工作成果。SysML 建模人员只需要通过模型如实描述并验证。
即使 SysML 建模人员已经通过 SysML 建模严谨地推导出信息系统的责任,包括输入什么 信息,输出什么信息,从输入到输出计算的规则是怎样的,也就是说把 B-需求都给描述清楚了, “发动机中控系统”的内部部件以及部件之间 的关系依然是不知道的,需要“发动机中控系统”的开发人员自己构思 和实现——100 个团队可能有 100 个不同的构思。
“地球发动机”的部件以及部件之间的关系,可是其他专家团给出 来的,并不需要自己构思。这一点就使得“发动机中控系统”的建模要 比“地球发动机”更难。
当然,如果领导只是吩咐一句,做一个“地球发动机”,剩下所有 工作都由 SysML 建模人员来做,那难度可就大了。 “反应堆”《流浪地球》原文提到的“重元 素聚变”应该属于“反应堆”的责任。我用 SysML 画了一张活动图, 如图 1-17。可以看到,这个过程处理的是能量(物质),原料和催化剂 进来,变成能量出去(当然,还有废渣)。
打问号的地方,例如聚变过程的各个步骤应该怎么进行,催化剂是 哪些,需要什么样的反应设备(1000 万℃的高温啊!),这些难题都需 要各个学科的专家去攻克。和这些难题相比,通过 UML 建模构思信息 系统的内部结构的难度就不算什么了。
信息系统可以看作是人脑的替代。像上面说的“根据接收到的测量 参数值(可能有上万个),计算地球发动机下一步的最佳行动”,这个事 情人也可以做到,因为计算的方法就是人指定的嘛,只不过人算得很慢 很慢,所以用信息系统来做。
也就是说,我们建造信息系统是要把人脑总结出来的各种知识转移 到信息系统中,并用它来取代人脑来做计算。信息系统的一切,包括规 则如何表达,数据如何组织,各个部分的耦合、内聚等等,都需要我们 一个一个构思。
目前,非信息系统的建模还没有“取代人脑”的压力,SysML 更 多是描述和帮助验证。
目前正式的 SysML 最新版本是 2024 年 12 月的 v2 的 Beta 2.3。 从目前的信息看,SysML v2 有很大的变革,特别是大刀阔斧地清理术 语。 UML 虽然把各种软件建模“方言”统一成“普通话”,但仍然做了 一些妥协,留有各种冗余的尾巴。衍生自 UML 的 SysML 也不可避免 存在冗余的问题。SysML 把非必要的术语全部清理(和领域驱动设计 圈子热衷造词形成鲜明对比),这是非常值得期待的。
SysML最新规范: https://github.com/Systems-Modeling/SysML-v2-Release
因为 UML 和 SysML 两者非常相似,学习了一个相当于学习了另 一个。如果你的工作只是开发信息系统,那么学习 UML 就可以。如果 你的工作确实涉及到开发信息系统和非信息系统,可以直接学习 SysML。在碰到不好用 SysML 建模的问题时,再适当引入 SysML 所 没有的 UML 元素。
一条双赢的路线是:SysML 发展到足以覆盖现在的 UML 后,吞并 UML,然后把自己改名为 UML——比 UML 还统一的统一建模语言。 2005 年,SBC 电信以 160 亿美元收购 AT&T,然后把自己更名为 AT&T。