UML释义(三)——开始建模
Error.cao
(本文转载自软件工程专家网www.21cmm.com)
从设计程序之初我就没有打算把建模让给别人去做,我这并不是自私,引用两句名言来说明我的观点:一拿破仑:“不想当将军的士兵不是好士兵”;二张五常先生的《经济解释》“要现实公司利益的最大化,必然使得能让公司最大化的人来当排头”。
我虽然没有从出生以来就开始注意建模,但也开始学习搭积木了,大家和我一样期待着成为软件模型的设计者,但是要怎么样做,又从那开始做呢?
在给UML栏目写东西的时候,我一直从事软件开发,是中国传统方式的操作—作坊式的,公司三五十来个人,连个软件小组都称不上。我虽然不是软件开发组的组长,但我是唯一的一个把文档整理好给别人的人。我告诉同事我的三个优点:我很会和客户打交道;我很会写一份详尽的文档;我很会整理,使得一件复杂的东西简单化。
一. 开始构想我们的软件
除了无用的哲学理论之外,我还不知道哪一件东西可以凭空产生。我们开发的软件是供别人使用,学过经济学人都知道经济开始的三个要素:为谁生产?生产什么?如何生产?
我们可以围绕这三个因素来开始谈论软件建模:
a:为谁生产
在软件的领域内我简单把该项过程考察为:软件的需求分析(在最近几期的《程序员》杂志上有高展先生的详细论述)。站在客户的角度(客户正是我们为之生产的对象),有两个方面的需求:一是该软件产品符合操作规范;二是该软件产品操作简单方便、界面友好。许多人都知道软件开发过程中的许多问题,都是由于收集、编写、协商、修改该软件产品的代码、文档(有的人把代码也列入文档)时由于失误、马虎、未确定或不明确等因素造成的。 我在软件工程上找到“客户”两个字的解释:是指直接或间接从产品中获得利益的个人或组织,包括提出要求、支付款项、具体说明或使用软件产品的项目风险承担者或是获得产品所产生的结果的人。
其实,客户的如此两个字并不能说明我们为谁生产的生产对象,作为软件的开发者已经很了解各个软件开发的差异性,假如说客户是机器(当然机器也是人操作的吗?),我们为之开发驱动程序、操作系统等;如果是商业使用我们为之做CRM、ERP等商务软件或与其相关的财务软件。如此说明就象我们是在建造商务楼还是在造民房。
当然为谁生产的本质并不重要,因为它们在实现起来是一样的。
b:生产什么
没有不骂我是白痴的,讲了半天的软件了,还在问这是生产什么?
如此说法是正确的,但仔细一想就知道这个问题的答案还很难回答,虽然这是微软风格但也必须把它说明。
在为谁生产的问题中已经有些说明了,生产什么,当然是用户说了算,我们生产什么,我告诉你:“我们生产用户所需要的”。但用户到底是需要什么?在软件的需求中我们赋予用户一些权利:可以要求软件使用客户语言规范;要求软件跟踪客户的系统业务目标;要求软件对产生结果或数据进行详细的说明;要求软件符合质量要求。
根据软件的种类我们来列举一大堆的例子分析说明我们软件开发者生产的是什么:操作系统啦、驱动程序啦或者媒体播放软件啦......
其实不然,我生产的是根据用户提出的软件设计的模板来进行软件生产。
c:如何生产
先谈谈分析和设计的区别:“分析是一门科学,设计是一门艺术”,说话者的意思是在所有的“正确”分析模型中只存在一个最“正确”分析模型可以完全满足解决某个具体问题的需要;当然软件的建模也同样是合乎其理的。需求分析需要一丝不苟、精确的完成,而软件设计的时候反而可以发挥创造力和想象力,不然世界没有进步了。
在实际的操作过程中,软件的设计者(我还不能包括在内)常常遇到一个问题就是:对软件的理解在开发的过程中才愈来愈深,在设计的初期软件的设计者并没有对软件如此理解,如此便造成一种假象:好象是需求经常改动。其实不是,客户对待软件的需求并没有变,但由于交流或其他方式的接触,使得软件设计者对软件的理解加深了,我们改变了对需求的理解而不是需求变。
根据软件的需求,我们如此而知到软件开发的目的。
有了目标我们必须找一条路走过去,而这条路就是如何生产了。
首先,软件的设计不可避免的需要写文档,按照软件设计规范,软件文档有十三种,每一种对应于软件开发的一个时期(具体的内容以后再谈)。
其次,根据软件的文档开始编写代码,该代码就是软件的源代码,源代码的开发在目前的国内软件开发上还是占据主要的份额(其实这个问题在我身上基本上消失了)。
再,软件测试,具统计很少有人愿意干此类的活,虽然每个人都知道该项很重要,在前面的释义(二)我已经讲了心态的问题了。
最后,把开发好的软件放在有电源的设备,并为之添加硬件和软件的环境支持,使其运行。在运行的过程中进行软件维护。
二. 做些准备工作
别把建模当回事(当然说这个话是有目的),建模就是让别人知道如何操作自己而来实现别人对你的要求。模也就是一个Document(使用MFC的兄弟应该对此有很深的体会),但如何把Document叙述的详尽,完整和条理,为此我们(当然不包括我了)利用UML定义了一套标准来规范文档的写作。
为此,理解你要实现的东西是一件建模初期的事,在理解的基础上我们并不能忽略现实的简单性,所以,好的软件设计人员把大多数时间花费在建立系统模型上,偶尔写一些源代码,但那只不过是为了验证设计过程中所遇到的问题。这将使他们的设计方案更加可行。 我在工程的实践中,遇到了一系列问题,但问题反映出来,其原因有如下几个大问题:
1. 设计者就是设计者
设计者如此费力地把模型搭建起来,然后再费力向各个程序员详细地说明该软件开发的具体步骤,若程序员的水平太差,再给他们写些原代码示例,如此以来,还不如自己写算了,设计者就是设计者,并不需要实际深入地参与软件原代码开发,但应参与其他文档地编制。习惯了好象我们成了幼儿园的老师。
2. 教育你的程序员
你花了很大力气建立一个很成熟的系统模型,而你的听众却不能理解它们,甚至更糟-连为什么要先建立模型都不知道。那么你的工作是毫无意义的。
教给你开发人员基本的建模知识;否则,他们会只看看你画的漂亮图表,然后继续编写不规范的程序。其实该问题是如此地实际,但也正是该问题困扰着我目前的开发状况,例如:我用Playcase的开发工具做了一套流程,使得程序编写起来模块化,第一没有人看懂如此设计文档,我开始讲述如此建模知识;第二有些开发人员学习过其他的建模语言,对此开发工具指手划脚,其实工具并不重要,重要的是用它来实现东西。
另外,你还需要告诉你的用户一些需求建模的基础知识。给他们解释你的用例(uses case)和用户界面模型,以使他们能够明白你要表达地东西。当每个人都能使用一个通用的设计语言的时候,你的团队才能实现真正的合作。
3. 在现有任务中应用多个模型
当你收集需求的时候,考虑使用用例模型,用户界面模型和领域级的类模型。
当你设计软件的时候,应该考虑制作类模型,顺序图、状态图、协作图和最终的软件实际物理模型。
程序设计人员应该慢慢意识到,仅仅使用一个模型而实现的软件要么不能够很好地满足用户的需求,要么很难扩展。
4. 证明你的设计在实践中可行
在设计的时候应当先建立一个技术原型,或者称为“端到端”原型。以证明你的设计是能够工作的。软件的设计最忌讳的就是使用不成熟的技术来开发软件产品,我的朋友和谈天的时候说:“我用最成熟技术开发最实用的软件”,“首先客户需要的是一个成熟的软件,稳定、可靠,如果采用最新的技术,由于没有经过时间的检测,不能保证其运行的稳定性”。
你应该在开发工作的早期做这些事情,因为,如果软件的设计方案是不可行的,在编码实现阶段无论采取什么措施都于事无补。技术原型将证明你的设计的可行性,从而,你的设计将更容易获得支持。
5. 管理接口和使用接口组件
你应该在开发阶段的早期就定义软件模块之间的接口。我是电子商务软件的,对于COM/DCOM组件的使用需要深入地研究下去,这个研究的目的就是使得软件模块的接口方便、简易、易于管理。
接口或接口型组件将有助于开发人员全面理解软件的设计结构并取得一致意见,让各模块开发小组相对独立的工一旦模块的接口确定之后,模块怎样实现就不是很重要了。从根本上说,如果你不能够定义你的模块“从外部看上去会是什么样子”,你肯定也不清楚模块内要实现什么。我想再说一次爱因斯坦的话:“外部的证实,内部的完备”。
6. 软件的移植性和封装
移植是软件开发中一项具体而又实际的工作,不要相信某些软件工具的广告宣传(当然广告的宣传是带有软件的商业性质)。
即使仅仅对软件进行常规升级,也要把这看得和向另一个操作系统或数据库移植一样重要。记得从16 位Windows 移植到32 位windows 的“乐趣”吗 (微软公司又开始挣我们的钱了)?当你使用了某个操作系统的特性,如它的进程间通信(IPC)策略,或用某数据库专有语言写了存储过程(DCOM/Istorage或其他策略)。你的软件和那个特定的产品结合度就已经很高了。
好的软件设计者把那些特有的实现细节打包隐藏起来—我比较随便把这种东西叫封装(也可能我是C++等OO技术的爱好者),所以,当那些特性该变的时候,你的仅仅需要更新那个包就可以了。
7. 降低软件模块间的耦合度
高耦合度的系统是很难维护的。一处的修改引起另一处甚至更多处的变动,其实这种变动在数据库领域内更让你有很深的体会,尤其是现在人们常用的关系数据库,修改起来很象株连九族一样。
你可以通过以下方法降低程序的耦合度:隐藏实现细节,强制构件接口定义,不使用公用数据结构,不让应用程序直接操作数据库。
耦合度低的软件可以很容易被重用、维护和扩充(那什么软件耦合度低—采用中间件,这么这些都是我喜欢的)。
8.最后的绝招
询问.学习.整理。
这个没有人教的,全是我悟出来的。但这是软件设计人员的过程:1、询问客户建立需求文档;2、学习研究需求文档,测试设计的可行性;3、整理文档,编写设计文档。