当今对象导向开发的世界中,第二条大新闻是什么?那就是『统一模塑语言』(Unified Modeling Language; UML),其不仅获得对象治理小组(Object Management Group; OMG)所承认,也将取代 Booch、Coad、Jacobson、Odell、Rumbaugh、Wirfs-Brock 等分析及设计方法原先所使用的表示法,成为全新唯一的表示法。此举将终结软件开发人员究竟要使用那些方法,这类令人生厌的争议,我们将进入和睦、友爱及提升生产力的新时期(就算那些旧架构的方法已经相当成熟了,却从未达到这样的水平, 对此也只能一笑置之)。
假如你是 B.S. (before standardization; 标准化之前)方法之一的方法迷(keen user),你钻研(bite the bullet)、转换至 UML 时,不免暗地抱怨,没有看到你所喜爱方法中的 x 特性,而你所不喜欢的 y 及 z 特性却充塞其中。但是,你是否真的冷静下来,思考像 UML 这样的塑模表示法,为何是有用的吗?
询问一位方法论大师(methodologist; 在我们业界指的是创造方法论的人)有关这方面的看法时,会招致一顿软件质量如何如何的严厉训斥。方法论大师会谈论到,我们的产业遭受到怎样的危机,缺乏软件质量所遭致的问题,良好设计的重要性 ... 等等。这样也好(虽然我想软件产业在最近几十年已经做得很好了),但是如何确实地实施 UML 才是有帮助的?询问 CASE 工具厂商时,你将会上一堂课,是有关改善质量、文件自动化及程序代码产生器的生产值,然而我们大家都知道,CASE 工具厂商接下来的动作会是什么。
假如你是一位开发人员,质疑所有方法的本质,不过是另类的治理流行时尚,你一想起会产生毫无用处的纸张,就感到战栗,然后 UML 恰好佯装成关怀这类问题,而成为另一种表示法(notation),至少这是目前仅有的。可是,你也了解下次你必须更改系统时,在你必须修护程序代码往后的几个版本,这些 UML 图还是有所帮助的。
我早在软件职业生涯中学会方法,既使我具有工程的背景,然而这些方法似乎成为一种天然的知识领域,这般的吸引着我。大多数的工程科系采用绘图来描述如何建构事物,同时相当专心的 ,根据这份设计图来做这些事物,我明白方法论的图型也具相同功效。有段时间,我学习类似的方式(the lie of that analogy),然而我仍然发现这些方法是有用的,尽管我对于某些开发人员不喜欢这些方法深表同情。
接着下来我要说明为何我发现 UML 是有用的,首先我快速的提醒各位, UML 『是一种塑模语言,而非方法(或方法论)』,同时以此作为下面论述的开始。UML 订定了一些图型,以及这些图型的意涵。而方法则更进一步描述开发软件的步骤,什么样的图型在什么顺序中产生,由谁来做那些工作 ... 等。支持 UML 的方法是各自独立的,过了明年或明后年,我们将看到不同人士提供各种运用 UML 表示法的方法。然而,你不须要使用方法,才会利用 UML,在这篇文章里,我不去假定任何特定的开发方法。
因此,假如我们除去所有方法的装饰,除了少数你能够绘制的图型样式外,被留下来的还有什么?这个问题,从「UML 有什么用途?」变成了「这些图型有什么用?」
答案可以归结成一词:『沟通』(译注:英文是一字:communication),这是一个重要的词汇,软件如此地迷惘 ,以致于难以开发的原因,主要就在于沟通。我们知道,假若我们只要在周末偷闲一下,而程序代码就此消失,事情将是如何简单,困难的症结在于我们必须与多位开发人员沟通。UML 之所以重要,就是因为它有助于软件开发人员之间的沟通。我们必须在某种程度上使用它,以协助沟通,而非阻碍沟通。
图解 1. UML 图型,用以展示 java AWT Container 类别的 Container
图解 1 说明了 UML 如何协助沟通的范例,此图型一开始是用来描述 Java 抽象窗口工具集(Java's Abstract Windowing Toolkit; AWT)的容器类别(Container class),透过阅读这个图型,我能够了解一大堆东西。我能够了解容器(Container)是组件(Component)的子型态(suBType),可以把组件制作成可视的(visible)或主动的(active),以及其它类型的组件,这些组件包括卷标(labels)、按钮(buttons)以及其它种种。我可以询问一个容器有关它所包容的组件,但是并非所有的组件都需要容器。容器(Containers)包含组件(Components),容器(Containers)也可能包含其它容器(Containers),同时容器拥有一个布置治理者(layout manager)。容器就如同组件般,属于抽象类别(abstract class),其子型态包含画板(panels)及窗口(windows)。窗口能够显示及处置窗口本身,窗口也有框架(frame)及对话框(dialog)两种子类别(subclasses),两者皆有标题列,同时能够设定其大小是否可以变更(resize)。虽然窗口的两种子类别都可以做上述的事,然而这些行为并非窗口本身的一部分。可以将对话框(Dialogs)标示为模块式(modal),然而框架(frames)却不可以。
你可能喜欢这个图型,也有可能喜欢我前面那段论述,这端赖你是否熟悉 UML,以及你是喜欢可视化的叙述,或者喜欢叙事式的陈述。关于此,我喜欢可视化,然而有些人喜欢文字方式,即使他们也懂得这些图型。你可以给他们文字描述,或者(或许会更好)给他们一段程序代码选集(如列表 1 所示)。那一个是你愿意选择的?那一个是你的同僚所想要的?这些问题对于 UML 及类似语言的角色是至关紧要的。我发现有些人喜欢文字的方式,有些人喜欢图型的方式,还有某些人在某些事物上选择图型,同时在某些事物上选择文字。最后,图型仅有在可以强化沟通的情况下才值得去做。
除了注重那些图型展示甚么之外,你也该注重到那些图型不能够展示甚么,类别整体描述有较图解 1 或列表 1 所标示的接口更大。我未曾提到布置治理者(Layout Manager)是一个接口,或者那个组件实作若干接口,许多人可能会因此而责难图解 1 不够完整。它是不完整,但不完整是一种缺点吗?在图型里,我决定去描写那些类别的特性,并且慎重的决定那些不该显示出来。事实上,我所显示出来的某些特性,就是我所要突显出来的特性。
选择所要强调的信息,是沟通很重要的一环。在类别的任一群体中,为了取得这些类别最初的理解,去了解某些观点(aspects)是相当重要的。假如你展示每件事,你会失去引出那些特点,同时你的读者会对于首要了解的事物,以及往后才须专注的细枝末节毫无概念。当我使用类别图,我是为了最初的理解而利用它们,以便于了解我想表达这些类别的要害观点。我知道读者经常是从 Javadoc 档案中,去取得这些接口完整的叙述。
我鼓励你以这种有选择性的方式来使用类别图,这样做不仅可以促进图型沟通的价值,也可以使它们轻易维护(keep up to date)。你无须为了类别每一个小改变就变更图型,既然难以维护这些各式各样的图型,为重大的问题之一,这种做法就有相当大的好处。
就像鼓励有选择性一般,我也鼓励人们去强调接口(interface)而非实作。我在组件上显示一个 isEnabled 的属性(attribute),这不是说组件类别有一个数据域位(field)称为 isEnabled (我真的没有注重到,因为它无关紧要)。其所表达的意思是你可以假设这个类别有这样的属性,然而你要从类别外部透过适当的操作(Operations)来存取内部的数据。理论下,可能有这些操作的命名约定(在 Java 链接库的这些日子,命名的方式为 isBooleanAttribute 及 setBooleanAttribute)。我不显示类别的操作,因为我发现属性的表示方式 ,更能适当地传达程序代码的意图。属性也可延伸至结合关系(associations),我不知道容器(Container)及组件(Component)之间存在那些数据结构,这些操作会使人联想到这些结合关系。
许多人士以实作的观点来绘制类别图,即是将属性(attributes)及结合关系(associations)反映至数据结构中,这些数据结构之所以有用,乃在于你期望表达甚么。无论如何,通常 这些接口那些是最重要的。你该决定甚么是你所根据的观点,甚么是你想要表达的。
当讨论到某一件设计,还有你可能如何去变更它时,我发现图型也是有用的。 假如你拥有一群设计师正致力于一项设计,尝试在白板上绘制设计的草图,描绘几个替代方案。我发现我们在探讨有关事物时,可视化是很有效的办法。(CRC 卡是另外一种有效的技术。)
这项技术有一点非凡重要的变化,是发生在当我正与领域专家合作,尝试去了解我们所要建构的系统时。在这种情况下,我使用最少的表示法,并且聚精会神于领域专家脑中所描述的概念,而不是思考任何特定的软件情况。我发现教导这种概念上的塑模风格,对于没有软件背景的人士是相当轻易的。 接下来,使用这些图型, 我们能够共同地发展出一套定义正确的字汇,用于讨论领域相关事项,同时能够提出对于讨论及目的软件皆有益的抽象概念,当我从事于如保健及金融贸易这类复杂的领域时,这对我而言是一大恩惠。
统一规格在此是有用的,乃因其可加强沟通的质量,当他们使用各种图型式样(diagramming styles)与人沟通时,这种思想交流是困难的。拥有一个单一的标准,我们可以确认,假使人们懂得少许图型式样的话,他们一定懂得标准化的图型。但是不要走过头了,UML 包含许多表示法,并且没有规定说你全部都必须用到。尝试着运用这些表示法中适当地、少量的部分,不要使用进阶的概念,除非它们确有必要。虽然你应该尽你所能去忠于标准,然我必须承认,假如需要的话,我并不害怕去篡改表示法。我不这样做的原因,通常是每次篡改表示法就需要对此作说明,同时不是读者所熟悉的,但是若这么做能加强沟通,我就去做它。
所以,假如你是 UML 的新手,根据你所需传达的想法去尝试使用它,实验可以了解那些可以做,以及那些不可以做。 透过实作去学习表示法,并且逐步地学习