仓库源文

.. Kenneth Lee 版权所有 2019-2020

:Authors: Kenneth Lee :Version: 1.0

UML有没有用


本文是参与这个讨论:UML 还有用吗?。我反对该回答,但回复中不利于写很长很完整的 逻辑,所以我把完整逻辑建在这个地方。

首先,该答主最初是持“UML是一种语言,这种语言表达能力没有其他语言强,所以它落伍 了,不好用了。”这个观点的。但在我质疑后,他补充了很多内容,以证明:“编程语言也 可以表述UML能表述的内容。”

我对后一个讨论没有兴趣,因为如果你提出一种编程语言,也表述UML表述的内容,那恰恰 证明了“UML还有用”。如果该答主要表达:“这不是我的意思”,那我这个讨论的逻辑链不针 对他,我的讨论仅局限于“为什么UML是一种很有用的建模语言,而且一般编程语言不能取 代它”。

UML到底要表达什么?我们用一个例子来讨论。

比如,我们要提炼Linux driver,bus,device的关系,其实这个很简单,我简单画出来就 是这样的:

    .. figure:: _static/uml1.jpg

这是这三个东西关系的核心,driver和device都注册给某个bus,如果他们可以匹配,则两 者建立关联。

我不是为了争吵,但该答主确实给了一个好例子,它把这个模型抽象成这样的代码了:

    .. figure:: _static/uml2.jpg

其实这个已经算不上是代码了,几乎是上面那个图的翻版表达了。但它仍带入了很多时候 作为架构师不想带入的信息。我用前面的UML建模,我想强调的是driver和bus有一个1对多 的关联,这个关联到底是通过一个数组表示呢?还是通过一个链表表示呢?我并不在意。 我把这个目标留给了下一层开发者,他可以做出他的选择,我在意的是概念的关联:每个 driver,都可以和一种bus关联,driver和device之间,是1-1关联,仅此而已,我没有其 他意思。所以你在代码中定义bus这个class中有一个driver数组,这不是我的意思,你后 面的match函数,也不是我的意思。那不是我的架构限制,只是一种实现。这个实现是可以 换的。

你还可以争辩说:“其实我定义一个数据就是表示一种一对多关系,不一定是个数组”,啊 ,那就对了,你现在开始尝试做UML已经做了的事情了,然后你说UML有没有用呢?

我无意和该答主争意气的长短,只是想通过这个问题说明:架构是怎么“以少为多”的。我 们提炼一个独立的逻辑出来其实很困难,经常挖出萝卜带出泥。这是很多架构师向工程师 表达概念的时候最困难的地方,我们框架代码都写出来的,为了让它能跑,我们必然会加 上带来边界效应的选择,这样工程师又误解了。UML,DFD,STP这样的方法,给了我们一个 最核心的表达机会,我们要加其他约束,可以以这个为基础一点点加,这样我们才能保证 我们的意思可以有效传达。而那些希望把模型直接变成代码的努力,基本上是缘木求鱼的 。

这其实是个很好的例子用来说明架构设计是什么。很多人希望把UML,或者说建模语言,作 为代码的一部分。我觉得本质原因是,他们就不觉得做一个这样的模型是必要的。我这里 评审过各种各样的设计文档,很多人画UML图,都不是事前画的,而是事后画的。因为他们 把UML和代码看做一个东西了,觉得直接编码就可以了。这背后的原因,是因为他们心中的 程序目标,是几个月以后的,而不是几年以后的。而对架构师来说,你现在说下的一句话 ,一行代码,几年以后,在你控制不住之下,它会增长1000倍,10000倍。你这里定义了一 个数组,几年后它可能会变成一个无锁队列,还能产生日志,休眠的时候会进入特定硬件 ,恢复的时候会从硬件上恢复。这些全部是变数,架构师没有能力对这些每个细节进行指 定的,所以他们会被推到一个非常不起眼的位置上,但他们会控制关联,保证这个系统还 可以控制。还用上面Linux的设备驱动为例,Linux最早的驱动是这样的构架:

    .. figure:: _static/uml3.jpg

根本不用分什么总线,驱动和设备,你写一个内核模块,这个模块自己发现这个系统有没 有这些设备,然后一次把他们驱动起来,然后通过netdev,crypto这些框架暴露给用户就 好了。

这个虽然简单(对于刚开始的系统来说,本来就该如此。这也是为什么前面说,如果只考 虑几个月后的事,架构是无所谓的),但它控制了一条:驱动是个LKM(这个LKM是泛泛含 义,LKM可以退化为内核的一部分,那个表述属于另一个逻辑)。

后来发现这样不好,因为发现设备的驱动和真正的驱动是两群人,比如pice发现挂了一张 网卡,但网卡的驱动不是写pcie设备的人写的,所以就会在这个基础上做出这样的关联控 制:

    .. figure:: _static/uml4.jpg

在这个描述中,架构师不介入代码实现的深入定义,而是聚焦在在哪里建立关联。基于这 个关联,原来的代码关系都没有改变,但驱动本身发生巨大的架构调整,但对系统的影响 是有限的。其实你可以看到我这里这幅图,和上面作为例子的那副bus,driver和device的 图的表述已经不一样了,但其实建立的是同一个约束。

不知道这个描述是否让读者对“架构是什么”有更多的认识?只有你有这个认识,UML才是有 用的,否则它就真得变成“聊胜于无”的东西了。其实更尖锐一点说,如果你不能这样用它 ,而指望用它来表征代码行为,这东西不是聊胜于无,它是“浪费时间”。

补充1-20190507:

说点和架构和《道德经》都有关的哲学。

在前面提到的那个回答中,有人这样回复了我的评论:

    | 我感觉 RDF 已经可以做到 UML 想做的事了,用文本描述关系

我觉得他和那个答主一样,为了证明某种“观点是对的”,完全被观点所绑架了。我们原始 的目标是为不同的工作找到合适的工具。如果要找一种工具,我当然找和我目标一致的东 西来用了,如果那个东西不符合我的目标,我也不用批评它,我直接就放弃它了。

UML的目的是为不同的建模场景建立描述“关系”的语言。使用这种语言是有需求的,他们也 这样做了,这已经足够成为架构师选择它的原因。然后你说,RDF也是可以做到的,(而且 ,为了证明观点:它是文本的)。问题是RDF的定义,从一开始就说自己是定义Web资源之 间的关系的,目标都和你不一样,它不够用,你连批评它都是不对的。因为人家整个目标 都不是这个。

绝学无忧,说起来高大上,其实你会发现这是非常Solid的,在生活工作中无处不在的简单 道理,只是你看不看得见它而已。这个问题,文人要特别小心。文人相轻,语不惊人死不 休,这些都是求名的陷阱,被“学问”晃瞎了眼,就看不见道了。