UML 是 Unified Modeling Language 的缩写,意思是统一建模语言。虽然叫做语言,但是压根没有一种计算机语言的样子,实际上是一些软件开发过程中画图的规定而已。虽然这是一个“标准”,比较搞笑的是,在 wiki 上记录着:在软件工程中,大多数从业者不使用 UML,而是制作非正式的手绘图表;然而,这些图表通常包含来自 UML 的元素。
UML 的诞生,就是来源于“面向对象”思想的流行,所以不用抬杠为什么没有包含“函数”和“变量”的代码结构图示——结构化编程基本上用传统的流程图就 OK 了。但是 UML 也不仅仅是用来画出“对象”“类”这些东西的。由于这个东西本身是一种画图的规定,所以并不会要求使用者 100% 准确,而是希望大家能看懂,能画出来就好了。UML 的标准好像已经更新到版本 2 了,不过具体有啥差异也许不太重要。所以我也主要是想介绍几种常用的 UML,特别是这种图的用处。
类图是用来表达,你的项目中的各种“类”之间的耦合关系的一种图。如果你使用的语言没有“类”关键字,但如果有“类”的概念的,也可以用这种图来表达,无需纠结是不是要把“原型链”上的对象都画出来。类图的基本单元就是“类”,每个矩形里面写上一个类的名字,表示这个类的存在。矩形下面可以再分成上下两格,上面是属性变量,下面是方法函数。
上面这个图是一个简略的画法,如果你需要更详细表达,可以参考下图。不过一般我们画图主要目的是沟通,私有类成员经常都会省略掉不画出来,也就不需要标记什么 + - #
所以 A 类和 B 类就有了关系。如果是 A 类的代码中有如同上述情况用到 B 类,我们就叫 A 类依赖于 B 类,在 UML 中就需要画一个箭头,从 A 类指向 B 类。注意,类图之间的箭头,是和运行时程序的数据流无关的,完全就是代码里面各个类之间的关系。简单来说,你的源码里面的每一行 import(或者类似语句),都可以在类图上表达为一根箭头。箭头也分为几种样子:
实际上,大家在用的时候,不会完全的把所有的细节都画出来,过于严格的去标注加号、减号,或者是箭头的样子、箭头线段是否虚线,其实都是不必要的。最关键的是把类之间的关系表达清楚:哪些类之间是关联的,是怎样关联的。很多设计模式的书,都会用 UML 类图来说明代码中的耦合关系,但很少需要严格区分聚合和组合、关联和依赖、继承和实现接口。比较需要注意区分的是继承和关联这两种就好了。
类图中最重要的东西,是箭头的方向,如果你的设计中,可以把所有类的箭头方向,都做成一个方向,譬如从上往下,或者从左往右,说明这个设计非常不错,因为代表在着类之间的关系是分层的,这样很方便修改任何一个位置的类,因为依赖它的其他类是可以很简单找到的。但如果箭头的方向是打圈的、循环的,就代表类之间的关系非常复杂,任何一个类的修改,影响到的范围难以简单掌握。
某大厂的服务器端程序员,最爱“部署图”了,虽然不是标准的 UML 画法,但这是他们最认可的“架构图”。
和上面的“类图”不同,“部署图”并不关注源代码里面的信息,它要暂时的是系统运行时的进程之间的关系。由于现代软件一般都不会仅仅由一个进程来完成所有任务,所以需要说明多个进程之间,是怎样协作来共同完成功能的。特别是网站一类的系统,其分布式的架构更是由成千上万的进程和服务器构成。
部署图会标识出软件在运行的某个时刻,其所有“节点”的连接情况。所以有可能一个系统,在不同时间,这个图是不一样的。如果能简单的表示清楚不同时间下的情况,画到同一个图上也没问题,但如果随着时间不同,部署图上节点的关系有复杂的变化,就不能只用一个图来表达了。
从软件架构上来说,部署图最时候表示“运行时架构”,这种架构可以比较好的表示系统在运行性能上的设计。因为所有的缓存系统、数据库、进程之间的交互,都可以表示出来,所以性能瓶颈可能在哪里,就能从图上猜到一二。但是这种图能表示的信息也比较简陋,一来它无法展示代码里面的互相关系,所以对于计算密集型的系统来说,从部署图来看,是看不出太多东西;二来是一个系统可能会有很多不同的功能,这个图并不能展示具体某个功能的数据流程和节点使用情况,这也可能很影响对性能问题的判断。
序列图是一种特别直观的,对于多模块协作进行表示的一种图。
虽然标准里面有很多定义,但是我们也不必每个图都有全部以上的元素。需要注意的是,“对象”可以是一个进程,也可以是一个代码里的对象,或者是一个服务系统,但不能是某个“行为”。序列图可以很好的展现一个复杂的,经过多个对象处理的过程,但也有一个问题:它不能很好表示 if 这种分支判断的逻辑。如果只是一个正常流程,以及一系列错误返回流程,放在一个序列图里面表达,还可以接受。但如果有大量的分支流程,就没办法用一个序列图进行全部描述,有可能需要每个流程都画一个序列图。
在我们设计分布式的系统(可能是微服务)时,是比较需要用序列图把每种业务逻辑的处理流程画清楚的,因为涉及很多不同的进程和网络交互,如果没有一个统一的图,很难让人掌握整体情况。而且序列图要和部署图相统一,每个部署图上的节点,都应该曾出现在其中一个序列图中;而每个序列图中的对象,都应该能在部署图上找到。
UML 除了上面说的三个,其实还有很多不同的图,但是那些一般用的比较少。也有一些如状态图,其实并不是非常的直观(当然比没有图要好),失之细节过多过杂,影响阅读。
评论区
共 23 条评论热门最新