摘 要 销售管理系统是现代企业管理系统的一个重要组成部分,传统的系统分析设计方法已经难以保证软件开发的效率和质量,通过将UML应用于销售管理系统建模,可以加速软件开发进程,提高软件质量,支持动态的业务需求,并方便地集成已有的企业管理资源。
[b] 关键词 [/b]销售管理系统;UML;分析;实现
1 引言
当前社会对信息系统的需求日益增长,需求变化也越来越快,软件开发的技术发展方向已经从“提升被开发系统的执行效率”转变为“提升开发效率”。面向对象(OO)技术降低了解决方法域与问题域的差别,提供了良好的复用机制,能够更加有效提高软件开发效率,完全顺应了软件开发技术的发展方向。
UML(The Unified Modeling Language,即统一建模语言) 是一个通用的标准建模语言,可以对复杂的系统建立可视化系统模型,目前已经被工业标准组织OMG(Object Management Group)接受,一经推出便得到许多著名计算机厂商如Microsoft,HP,IBM,Oracle等支持,在国际上应用日益广泛。
本文通过一个销售管理系统的分析与设计,阐述如何通过UML降低开发难度和提高开发效率。
2 销售管理系统的基本特征和功能模块
本系统以“订单”为核心,构建出了以“客户”为中心的管理模式。
该系统具有以下一些特征:
(1) 先进的系统结构,面向销售流程,能适应原有销售工作流程并进行合理的改进,从而更贴近实际的应用;
(2) 针对大型企业销售管理人员多,销售管理复杂的特点,通过系统提供的灵活的人员权限设置和全面的财务核算方式,实现真正的销售网络化办公;
(3) 在实现订单的电子化、工作流程的数字化同时,帮助公司领导提高决策的科学化水平;
(4) 通过对客户信息的管理,实现对客户广告走势和重要客户情况统计和分析。
整个系统操作业务人员包括:销售员、销售经理、仓库管理员、审计员、公司销售主管、和系统管理员。各个角色承担不同的系统任务,通过网络和通信系统,连接到销售管理系统,使用统一的访问界面,进行日常的销售业务操作,最终实现销售部门业务的正常运转。
3 系统的UML分析与实现
UML概述及特点
UML是一种编制系统蓝图的标准化语言,可以对大型复杂系统的各种成分可视化说明并构造系统模型,以及建立各种必要的文档。UML通过三类图形建立系统模型:Use Case图,静态结构图(类图,对象图,组件图,配置图)和动态行为图(顺序图,协同图,状态图,活动图),这些图可以从不同抽象角度使系统可视化。UML具有面向对象、可视化、独立与开发过程和程序设计语言以及易于掌握使用等特点。UML适用于各种规模的系统开发,能促进软件复用,方便地集成已有的系统并有效减少开发中的各种风险。
UML在销售管理系统中的实际应用
UML是一种建模语言,是系统开发的一个组成部分,本身并没有关于开发过程概念的定义和表示符号。UML的创始人 booch,Jacobson和Rum Baugh在rational公司的支持下综合了多种系统开发过程的长处,提出新的面向对象的开发过程,称为Rational统一过程(Rational Unified Process,RUP)。RUP过程的核心工作流程包括:业务建模、需求分析、系统分析与设计和实现、实现、测试和系统部署。下面通过UML来分析并构造销售管理系统模型,并结合Rational统一过程加以描述,图形使用Rational Rose 工具软件绘制。
[b]
3.1
[/b] [b]
销售管理系统的业务建模和需求分析
[/b]
业务模型和需求分析的目的是对系统进行评估,采集和分析系统的需求,理解系统要解决的问题,重点是充分考虑系统的实用性。结果可以用一个业务用例(Business Use Case)框图表达,根据销售系统的基本特征和功能可得到 本系统的用例图,如图2。
[b]
[/b]
图1 销售管理系统业务用例框图
模型中的活动者代表外部与系统交互的单元,包括销售员、销售经理、仓库管理员、审计员、公司销售主管、和系统管理员;业务用例框图是对系统需求的描述,表达了系统的功能和所提供的服务,包括客户管理子系统、订单管理子系统、销售统计子系统、产品管理子系统系统管理子系统。
图2是销售管理系统层次的用例模型,只包含了最基本的Use Case模型,是系统的高层抽象。在开发过程中,随着对系统需求认识的不断加深,用例模型可以从顶向下不断细化,演化出更加详细的Use Case模型。 根据系统的用例图,可以对系统的持久对象进行设计,下图是本系统持久对象类及类之间关系图。
图2 核心业务对象类及类之间关系
[b]
3.2
[/b][b]
销售管理系统设计
[/b]
系统分析与设计是研究欲采用的实现环境和系统结构,结果是产生一个对象模型,也就是设计模型。设计模型包含了Use Case的实现,可以表现对象如何相互通信和运作来实现Use Case流的。对于系统的静态结构,可以通过类图、对象图、组件图和配置图来描述;对于系统的动态行为,可以通过顺序图、协同图、状态图、活动图描述。这些图在加上说明文档就构成一个完整的设计模型。
[b]
3.2.1系统架构设计
[/b]
销售管理系统拥有大量销售信息资源,这些资源包括各种客户、订单、和产品等信息。其数据量大、信息变化快,非结构化信息与结构化信息共存。使用UML对销售管理系统进行基于面向对象的分析和实现,可以从开发的第一步开始,从系统的底层就把握住销售信息资源的特征,为下一步具体实现打好基础。在销售管理系统建立模型时要涉及到处理大量的模型元素,如类、进口、组件、节点、图等,可以将语意上相近的模型元素组织在一起,这就构成了UML的包,包从较高的层次来组织管理系统模型。
系统主要有以下四个包:
(1)用户接口包(User Interface Package)
用户接口包在其他包的顶层次,为系统用户提供访问信息和服务。要注意一点,由于开发工具使用不同,该接口描述也是有区别的。如果采用Java Web开发,就要以JSP(Java Server Pages)为基础,如果采取Microsoft的Asp.net开发,其基础就是标准化控件组。本系统在此将使用Java Web开发,下面有关代码的描述都是基于Java的。
(2)业务逻辑包(Business Rule Package)
该包是销售管理系统业务的核心实现部分,包括客户管理、订单管理、产品管理等,其他包可以通过访问该包提供的接口,实现业务逻辑,如客户管理业务等。
(3)数据持久访问包(Data Persistence Package)
该包实现数据的持久化,也就是与数据库交互,实现数据的存取、修改等操作。
(4)通用工具包(Util Package)
该包主要包括应用程序安全检查的类,可以为上面三个包提供安全检查,如客户端检查和服务器端业务规则检查等,同时包括一些系统异常检查与抛出处理以及系统日志服务等。
[b]
[/b] [b]
3.2.2系统详细设计
[/b]
详细设计主要是描述在系统分析阶段产生的类,与分析阶段类的区别就是偏重于技术层面和类的细节实现。销售管理系统提供的各种服务都是建立在分布、开放的信息结构之上,依托高速、可靠的网络环境来完成的。每项服务都可以看作一个事件流,由若干相关的对象交互合作来完成。对于这种系统内部的协作关系和过程行为,可以通过绘制序列(Sequence)框图和协作(Collaboration)框图来帮助观察和理解。此外,描述工作流和并发行为还可以通过活动框图,表达从一个活动到另一个活动的控制流。同时,可以在理解这些图的基础上,抽象出系统的类图,为系统编码阶段继续细化提供基础。下面以Java Web开发为例,介绍客户管理子系统的详细设计
1.客户管理子系统的基本结构建模:下图是客户管理子系统主要类极其关系的详细设计
[/b]
图3 客户关系子系统类的详细设计及类之间关系
2.序列图:序列图是一种对象交互图,着重强调了时间序列,而不是静态对象的关系,通过序列图可以清楚地看到“谁在什么时间对谁说了写什么”。
[b]
[/b]
图4 客户管理的序列框图
图5 销售人员对客户管理的顺序框图
图4是一个客户管理的序列框图例子。描述了先加载某个客户;显示某些状态;再更改某些属性值,最后更新数据库状态的一次执行过程。此图可设计Customer类的loadCustomer(int)和updateCustomer()方法实现。
通过序列框图可以清晰看出系统用户、客户管理子系统的用户接口、数据库连接模块之间以时间为顺序的消息交换,这对于把握系统的控制流、顺序行为和交互行为是非常有益的。建立在分布网络环境下的销售管理系统的事件流和控制流是非常复杂的,需要从顶层到底层进行一步步分解,用多幅能反映动态结构的图来分析与说明。图5反映了销售人员对客户管理的顺序框图。
3.状态图适合描述一个对象穿越多个Use Case的行为。类的状态图表示类的对象可以呈现的状态和这个对象从一种状态到另一种状态的转换。
图6 Customer对象状态图
图6描述了Customer对象的生命期中可能的状态及状态变化(从创建、更新到消亡的转变过程),其中insertOrder/deleteOrder不是直接作用于当前customer对象,而是指当前customer对象所涉及的订单操作。此例说明其他对象的操作可能改变当前对象的状态。
4.协作图:协作图和序列图相似,两种图所表达的是同一种信息,可以将序列图转换为协作图,反之也然。但两者是有区别的,序列图强调的是交互的时间序列,协作图强调的是交互的语境和参与交互的对象的整体组织。下图描述的是查询一个客户信息消息传递的过程。
图7、查询客户信息的协作图
5.活动图:用于描述业务过程和类的操作,类似与旧流程图,是对业务处理工作流建模,在活动图中可以增加角色的可视化的维数,下图是增加了Customer、Saleman、Warehouse三个角色的系统活动图,反映了在业务处理过程中,每个角色执行的过程。
图8 活动图
通过框图,设计和开发人员可以确定需要开发的类,类之间的关系和每个类操作和责任。序列框图按照时间排序,用于通过情境检查逻辑流程。协作框图用于了解改变后的影响,可以很容易看出对象之间的通信,状态图描述了对象在系统可能中的状态,如果要改变对象,就可以方便地看到受影响的对象。
6.软件系统一般由一组部件组成,换句话说,部件是相对独立的部分软件实施,有自己特有的功能,并可在系统中安装使用,系统中各部件是相互协作合作,给系统提供完整的功能。下图是本系统运行时的主要部件
图9 运行的部件图
[b]
3.2.3销售管理系统的实现、测试和系统配置
[/b]
系统采用五层逻辑结构:客户端只需中文浏览器;表示层用12个JSP(Java Server Page)文档实现动态页面以创建、操作业务对象;核心对象层用6个Java类以JavaBean形式构成业务处理的核心对象;连接层采用JDBC2提供两种连接方式:一种是基于DriverManager,主要支持Java应用和测试;另一种基于DataSource;资源层即数据库服务器。
经过系统分析和设计后,就可以根据设计模型在具体的环境中实现系统,生成系统的源代码、可执行程序和相应的软件文档,建立一个可执行系统;进而需要对系统进行测试和排错,保证系统符合预定的要求,获得一个无错的系统实现。测试结果将确认所完成的系统可以真正使用;最后完成系统配置,其任务是在真实的运行环境中配置、调试系统,解决系统正式使用前可能存在的任何问题。
4 结束语
销售管理系统的发展方兴未艾,目前正处于传统手工、半手工管理向数字化过渡的阶段,转变过程中需要应用和集成最新的信息技术,以达到对网络信息资源最有效的利用和共享。传统的系统分析设计方法难以保证效率和质量,将 UML应用于 销售管理系统的建设,可以加速开发进程,提高代码质量,支持动态的业务需求。从实际效果来看,UML可以保证软件开发的稳定性、鲁棒性,在实际应用中取得良好的效果。
参考文献
[1]邵维忠,杨芙清.面向对象的系统分析[M].北京:清华大学出版社,1998
[2]Wendy Boggs, Michael Boggs.UML与Rational Rose 2002入门与精通[M].电子工业出版社.2002
[3]徐锋. 实战OO:为问题域建模. 程序员.2004.2
[4]王文玲,金茂忠.UML模型与其应用.计算机工程与应用.1999
[5] Doug Rosenberg, Kendall Scott. UML用例驱动对象建模. 北京:清华大学出版社,2003
个人简介: 姓 名:王文豪 性 别:男 出生年月:1973.2 学 位:硕士 研究方向:面向对象建模,数字图象处理 邮政编码:223001 电 话:0517-3591438 E-mail: wangwenhao1407 wangwenhao1407@163.com
积累┊技术
Excel函数应用之财务函数
像统计函数、工程函数一样,在Excel中还提供了许多财务函数。财务函数可以进行一般的财务计算,如确定贷款的支付额、投资的未来值或净现值,以及债券或息票的价值。这些财务函数大体上可分为四类:投资计算函数、折旧计算函数、偿还率计算函数、债券及其他金融函数。它们为财务分析提供了极大的便利。使用这些函数不必理解高级财务知识,只要填写变量值就可以了。在下文中,凡是投资的金额都以负数形式表示,收益以正数形式表示。
在介绍具体的财务函数之前,我们首先来了解一下财务函数中常见的参数:
未来值 (fv)–在所有付款发生后的投资或贷款的价值。
期间数 (nper)–为总投资(或贷款)期,即该项投资(或贷款)的付款期总数。
付款 (pmt)–对于一项投资或贷款的定期支付数额。其数值在整个年金期间保持不变。通常 pmt 包括本金和利息,但不包括其他费用及税款。
现值 (pv)–在投资期初的投资或贷款的价值。例如,贷款的现值为所借入的本金数额。
利率 (rate)–投资或贷款的利率或贴现率。
类型 (type)–付款期间内进行支付的间隔,如在月初或月末,用0或1表示。
日计数基准类型(basis)–为日计数基准类型。Basis为0 或省略代表US (NASD) 30/360 ,为1代表实际天数/实际天数 ,为2代表实际天数/360 ,为3代表实际天数/365 ,为4代表欧洲30/360。
接下来,我们将分别举例说明各种不同的财务函数的应用。在本文中主要介绍各类型的典型财务函数,更多的财务函数请参看附表及相关书籍。如果下文中所介绍的函数不可用,返回错误值 #NAME?,请安装并加载"分析工具库"加载宏。操作方法为:
1、在"工具"菜单上,单击"加载宏"。
2、在"可用加载宏"列表中,选中"分析工具库"框,再单击"确定"。
____________________________________________________________________
具体请下载附件察看。
AdSense Search for PJblog
首先,你要有adsense帐号,进入adsense帐号设置,选“adsense for search”,设置完之后得到一些代码,诸如
[code]
[/code]
然后,安装点击下载此文件这个插件
最后,新建一个侧边模块,输入第一步得到的代码。OK了。
注意,上述代码请用自己的adsense帐号生成。
统一用例分析
一、用例基础
1.1用例简史
用例技术大体上经历了萌芽、成熟和发展3个阶段[12],最早可追溯到上世纪60年代末UML(统一建模语言)、RUP(Rational统一过程)之父Ivar Jacobson(伊瓦·亚克申)博士在著名的瑞典爱立信公司领导程控电话交换机开发时采用的traffic case(话务案例),1986年前后亚克申博士在OOPSLA大会上发表的论文[4]标志着用例的正式诞生。1992年,亚克申博士在其名著《面向对象软件工程:用例驱动方法》[3]中正式推出了当时已相当完善的用例方法,用例驱动成为了Objectory过程(RUP前身之一)的核心内容,从此用例在国外软件工程界得以迅速普及,并于90年代中后期被RUP和UML吸收为核心要素,亚克申博士在《统一软件开发过程之路》[4]和《统一软件开发过程》[5]中对此作了精彩的阐述,这些书因为成为了解其用例思想的重要著作。如今,作为必不可少的关键内容,用例技术总是被所有的当代需求工程名著所引用,而“用例”本身也几乎成为功能需求的代名词。(注:考虑到历史上的渊源关系,为了方便起见,以下我们用术语“亚克申方法”或“亚克申用例”来统称RUP、UML及其支持者所采用的用例方法,尽管它们彼此之间可能存在细微的差别,而且也不一定全部是由亚克申博士本人所提出或赞成的。)
用例另一支主流派别代表人物Alistair Cockburn(阿里斯代·寇本)上世
纪90代初从亚克申那里学习了用例,随后通过十年认真广泛的实践对其进行了继承和发展。寇本于1995至1997年间提出了著名的“基于目标的用例”方法[2],他的方法和思想集中体现在《Writing Effective Use Cases》(以下简称为WEUC)[1]中,以结构化/半结构化文本用例为中心是寇本方法的一大特色,该书可以说是迄今为止最为详细的一本用例教材,对于指导实践者如何写好文本用例具有很高的价值。
1.2用例定义
下面,先让我们从什么是用例开始讨论。亚克申定义[7]强调用例是系统执行的一个动作序列(注:这其中也包括与用户的交互),这些动作必须对某个特定的使用者(Actor)产生可观测的、有价值的结果。(注:Actor实质上是用户所扮演的一种角色)
那么到底什么结果叫“可观测、有价值”呢?虽然两种用例本质上是一致的,但亚克申定义对此没有明说,而寇本定义[1]则更加完善和明确。它首先强调用例是各种系统受益人(Stakeholder,又译“干系人”)之间的一种行为契约(注:行为包括对象的活动、动作和对象之间的交互等),建立契约的目的是为了达成某种目标,因此每一个用例及其名称实际上都应代表一个用户目标,这个目标是否得到真正满足正是判断我们抽取的某个用例是否“有价值”的关键。寇本还点出了要通过用例的具体执行来展现Actor的目标是如何实现或失败的,而一个用例其实就是多个在不同条件下执行并可能导致许多不同后续状态的情节(scenario,又译“场景”)的叠加,这就是用例结果的“可观测”。
因此综合起来,我们只要抓住这样几个关键词:目标、行为契约、行为(事件)序列(动作和交互)、情节、可观测、有价值,就可以比较准确地描述出用例的本质特征。
1.3用例的重要性
为什么用例如此重要?一言以蔽之,这是因为用例是一种普遍存在的客观现实,而实践证明,用例技术是迄今为止最为深刻、准确和有效的系统功能需求描述方法。
功能需求是指系统输入到输出的映射以及它们的不同组合[9],任何功能必然要通过外部环境与系统之间的交互才能完成,这不正是用例所要反映的内容吗?因此,我们可以在内容和形式上把用例和系统的功能需求等同起来,并且得出推论:只要是软件,必然都存在用例(虽然有时候不一定非要用某种具体的用例格式来描述),其中即包含数据流,也包含控制流,既包含消息发送和数据交换(交互),也包括活动/动作的执行以及状态的变迁。这些就是用例的本质(现象背后那个真实的、抽象的“胚”),而各种格式文本、UML图形(我们至少可以用4种UML动态图来描述用例)不过是用例的外部表现形式。所以,与其说亚克申博士发明了用例,还不如说亚克申博士早在20年前就发现了用例这种客观现实,并最终发明了用例表示和用例驱动软件过程的方法。
那么,什么情况下不太适合采用用例方法?主要有两种情况:(1)用户很少或没有,接口也很少,如科学计算/仿真软件、杀病毒软件、编译程序、内存管理程序等[9];(2)功能需求非常简单,非功能需求和约束占主导地位。显然,如
今绝大部分的应用软件、系统软件,尤其像电信、银行、保险、税务、制造业、企业信息化等领域的复杂系统,都是符合用例适用条件的,这从一个侧面反映出用例技术的广泛适用性。请注意,即使在上面两种情况下也并不是说这些软件的用例就不存在了,而只是表明它们的功能需求很简明或不太重要,除用例之外可能还有更加适用的方法。
正确有效的软件需求必须是可测试、可验证的。过去我们描述功能需求可能采用了很多种方法,除严格的形式化方法外,普遍的缺点就是粒度太粗、精度不够,大多停留在受益人要求(request)和特性(feature)这一层[9]。比方说,针对某个“打印报表”功能,通常仅用一段话来描述它的静态输入和输出是不够的,还应该描述出用户打印报表的具体操作流程,它有哪些特殊条件和选项设置,以及它与其他需求的依赖关系等等。很多团队在需求尚未细化到用例这一层次时就开始匆匆编码了,结果往往导致大量需求风险乃至架构风险被隐藏到构造、移交阶段才发现,这必然造成频繁的返工和严重的资源浪费。及时准确地抓住需求契约——用例这一关键,可以帮助我们在不失实用性、灵活性的情况下,有效地避免项目后期大量非正常的需求变化,为进度愈来愈紧的项目赢得宝贵的时间,提高项目的成功率。
1.4相关译法
借此机会,顺便谈谈对use case有关术语翻译的看法。
笔者认为“用例”是目前较好的译法,这个词可能来源于大家熟知的“测试用例”。有人认为把use case翻译成“用例”是错误的[11],理由是:“‘例’是被列举出来以说明某种情况的个别事物,use case是对一项系统功能使用情况的普遍适应的描述,而不是对个别actor或者在个别条件下使用这项功能才适应,它也不是通过举例的方式来描述的”,所以不能叫作“用例”。此种说法不尽全面,而且有些牵强(先不管它正确与否),其实use case到底是个别的,还是群体的(普遍适应),取决于我们的视点。虽然对于单个的scenario来说,use case是多个情节的叠加,是一个整体的复合概念,但是我们知道,一个系统的功能必定是可数的、有限的,而每一个功能都可以表示为一个use case,所以在观察系统提供的所有功能需求的集合这个层面上,use case又是一个一个可数的个体(“椭圆”),每一个都代表了不同的用户目标,适用于个别的actor和个别特定的前置条件。同一个事物既是个体的又是整体的,这种现象并不足怪,例如在UML对象-类-类元关系中,通常对象是类的实例,而类又是类元的实例,对类元来说,类、接口、子系统、use case等等就是一个个个体的概念,类既是其对象实例的集合又是其类元集合的个别元素。可见,把use case的“case”译成“例”并没有错。
有的地方把use case翻译成“用况”,即“使用的情况”之意,意思的确不错(use case的另一种说法是“使用的方式”)!可我总感觉这个词比较突兀、拗口,类似的还有“用案”,把scenario叫作“案况”,大概这些词读起来不太符合大家的习惯(类似地,既然可以叫“用况”,为什么不能叫“用情”呢?),所以现在“用例”的叫法还是越来越多了。
其实“用例”这个译法还有个附带的好处,通过它我们很容易把原本就存在紧密联系的use case和test case(test case来自于对scenario的分析,而scenario是用例的一次执行)从中文名称上也方便地统一起来。不过,这里我
们需要做一个小小的改进。中文的“测试用例”到底是指test case(带定语的名词词组)呢,还是指对用例进行测试(testing the use cases,动宾词组)呢?显然这两者不易分辨,而且若“用例”和“测试用例”两个词同时出现在一啰个句子或一段话中,常常会让人感觉嗦和便扭。为了消除歧义,干脆以后把test case都叫做“测例”,这样不但比以前的叫法更加简洁明了,而且无论字面上还是语义上都很贴切。当然,用例和测例是不同层面的“例”。
现在市面上Actor也有多种译法,常见的包括“参与者、执行者、主角”等等。“参与者、执行者”的问题主要是不准确。首先,“参与者” 通常让大家马上想到的词是participant,而且请注意,一个用例的真正参与者决不是只有外部的Actor,它们必然还包括系统本身及其内部的各种元素。“执行者”的问题与此类似:一个用例的真正执行者应该是系统本身!因此严格地讲这样译是错误的,兴许叫作“外部参与者”、“外部执行者”才更为恰当。“主角”的译法同样存在着矛盾。如果把Actor叫作“主角”,那么Primary Actor就应该叫作“主主角”了。看来Actor的译法中是不能含有“主”的,那么就剩下“角”了,而UML已经有了一个专门术语role(角色),我们又不能把Actor直接叫作“角色”。
目前看来,把Actor意译成“使用者”是比较妥当的。在大多数情况下Actor的的确确就是用户(确切地说是系统用户所扮演的一种角色),所以我们可以用“使用者”这个词从字面上与“用户”(user)进行区分,但同时又保持两者语义上的联系。我们还可以把为系统服务的Supporting/Secondary Actor(见下文)叫做“被使用者”(为了简化可以省略“被”字)或“辅使用者”。除了指系统的用户之外,“使用者”还有另一层含义,即Actor是use case的使用者(或被使用者),这种关系在UML用例图上应该可视化地表示为它们之间的连线(关联)。这样解释不但说的通,而且更便于不熟悉软件技术的业务人员理解。
当然,我们也不排除将来会找到“use case”、“actor”等术语更好的译法。
二、统一用例方法
2.1 理由
为什么要提出统一用例方法(UUCM),有这个必要吗?
我们发现,虽然寇本用例起源于亚克申用例,但两种用例方法各自经过十多年的发展,彼此之间逐渐出现了一些显著的差异,而且由于商业或其他方面的原因,目前我们尚未看到两者将要融合的明显趋势。两种方法各有优缺点,寇本强调基于目标的文本格式,亚克申用例则更突出UML的作用,如下文所示,两者的差别至少有10处之多。对于实践者来说,如何处理好这些明显差异,避免使用上的误区,再者能否巧妙地做出取舍,实现熊掌与鱼兼得,这些都是非常现实的在实践中必须面对的问题。
笔者认为采用统一的用例方法,把亚克申和寇本用例两者结合起来,甚至融合其他的用例方法(据说已知的各种用例表示方法多达18种以上[2][6]),在理论和实践上均是可行和必要的,这可能是我们目前可以采取的最佳策略。但是,UUCM本身并不是一种全新的用例方法,而只是一种特定的处理方案。它是在对亚克申、寇本用例方法继承的基础上,试图消除这两种经典方法的不一致和矛盾,并探索可能的优化改进和后续发展,所以UUCM起到的作用与亚克申、寇本用例方法相比是次要的和微小的。
以下我们对两种方法的异同进行比较分析,并同时给出UUCM的建议。
2.2层次
明确提出用例的层次和范围划分,是寇本“基于目标的用例方法”的精华所在[2]。显然,每个用例存在的意义是为了完成一定的用户目标。寇本把用例划分为3个目标层次:概要层、用户目标层和子功能层,并通过引入巧妙的Why/How技术帮助分析者找到合适的目标层次,从而可以有效地把握用例的粒度(真正的用例最终应落实到用户目标层),防止用例情节的爆炸。
亚克申方法及其相关文献在介绍如何有效地控制用例的粒度方面,大体上只有这样两条基本的判定规则:(1)通过判断内容是否有价值可以防止用例过小(例如,“输入发货地址”的粒度就太小,这不是一个真正的用例,相当于寇本的子功能层用例);(2)通过判断具体内容是否可观测,可以防止用例过大(例如,“用户管理”就比较空洞,这不是一个有效的用例名称,相当于寇本的概要用例)。但如前所述,究竟什么叫“有价值”,什么叫“可观测”,如何把握好这个度,亚克申方法对此语焉不详,给RUP和UML的使用者带来了不少困惑,而寇本方法恰好出色地回答了这个问题。
UUCM:
通过寇本的分析,我们发现用例有纵向(层次)和横向(范围)之分,这些是非常有价值的概念,它们是对亚克申基础用例方法的丰富和完善,两者是不冲突的,完全可以在RUP相关的实践中加以运用。
值得注意的是,我们在实践中应该尤其关注用户目标层用例。寇本引入概要层用例的主要目的是为了包含一个或多个用户目标层用例,为系统提供全局功能视图,提出子功能层用例则是为了表达用户目标层用例的具体实现步骤。虽然有时为了简便,我们也把后两者叫做“用例”,但其实它们都不是真正的用例。
可能是为了防止滥用、误用用例的分解(这很容易引诱人倒退到结构化的功能分解),亚克申方法没有提及甚至有意回避用例的层次问题。亚克申博士在最近的一篇文章中[12]引入了用例片段的概念,这意味着我们应该把寇本方法中的子功能层用例叫做用例片段以避免名称上的混淆,看来这是今后一种比较好的处理办法。
2.3范围
关于用例范围的处理,两种方法基本上是一致的,都可分为业务用例、系统用例两种,区别在于寇本强调在格式上用图标或文字显式地表示出每个用例的范围,并且在用例层次划分的基础上提出了最外层(或最外围)用例的概念[13],这在亚克申方法中是没有的。
UUCM:
用例的本质就是对象之间的一种协作和交互,这些内容是属于需求还是属于设计,关键就看你划定的讨论边界。我们不仅可以用它来描述发生在系统边界上的功能需求(用例的常规定义),而且还可以同样的方式描述系统内部发生在子系统、构件、接口或类/对象边界上的黑盒交互,不过后者往往涉及到系统设计
范畴,属于用例的特殊用法,在做项目的需求分析时一般不予考虑。
正如寇本所提到的,同样一个用例名称,比如“取款”,可能实质上代表着两个截然不同的用例:一个是ATM取款(系统用例),另一个是银行柜台取款(业务用例)。所以在一个用例中明确标记出它的范围,是很有必要的。我们既可以用特定的图标,也可以用专门的格式字段来表明用例的范围,还可以对用例的名称加以修饰以便区分,比如“柜台取款”,“ATM取款”。
当前的讨论边界(SuD,the System under Discussion)一般比较容易确定,那么如何从用例的范围上判断一个用例是系统用例,还是业务用例呢?(这是一个出现率很高的FAQ)。有个小窍门:如果某个SuD或者用例的范围包含了人以及由人组成的团队、部门、组织的活动,那么针对这个SuD写出的用例必然是业务用例;如果该SuD仅仅是一些软件、硬件、机电设备或由它们组成的系统,并不涉及到人的业务活动,那么根据这个SuD写出来的肯定是系统用例。
由于系统(注意,这里的“系统”是指由软、硬件组成的IT系统)往往是业务的一部分,我们还可以得出推论:对于某个系统用例suc,通常总是可以找到一个业务用例buc,buc的范围要大于或等于suc的范围;当这两个用例的范围相等时,buc就是suc,或者buc的层次要高于suc的层次。
2.4 包含与扩展
由于各方面复杂的原因,如何更好地表示用例之间的关系一直是个争议不断的问题,而且恐怕在将来较长的一段时间内对此还难有定论。我们发现,寇本与亚克申方法在用例的扩展、包含、继承等关系的使用细节上存在着一些明显差异,其中很大一部分原因可能是由于现有文献对用例关系的定义不够精准和完善,导致大家在应用时各取所需、各自解释造成的。如果我们在实践中对这一情况不加以留意,就可能给需求的沟通和交流带来障碍。
2.4.1一头雾水
同样一对用例之间的关系,在寇本用例模型中是包含关系,在亚克申模型中却可能被表示成扩展关系。例如:
图1、寇本画法[1]
图2、《UML参考手册》画法[10]
UUCM:
为什么会有如此差别?为了说明问题,还是让我们先看看这几个用例的文本描述。《UML参考手册》写道:
基用例ATM会话:
显示当天广告
include(识别顾客)
include(验证账户)
————————– <可能的事务>(扩展点1)
打印凭条标题
————————– <凭条细节>(扩展点2)
登出
扩展用例取款:
收到取款请求
指定取款数量
————————– <产生的请求>(扩展点3)
付款
看到这里,我们就不难解释为什么图2把ATM会话与取款之间的关系画成扩展了(注:这本身可能不符合亚克申扩展用例的原则[4])。由于在身份验证通过后,顾客具体执行什么操作是不定的,可以是取款、存款、转账、查询等事务中的任何一个,将来甚至还有可能添加(扩展)新的功能,而ATM打印的凭条根据用户操作的不同,内容也将有所不同。这些内容的发生都需要具备一定的条件,属于可能的情况,这一点似乎很符合扩展用例的定义。考虑到这些因素,作者于是采用了图2的策略,把可能的操作和打印内容都从基用例中抽走。
然而不要忘了,除了扩展用例只有在特定条件下才能被触发之外,把一段内容提取为扩展用例还要求即使在没有该扩展用例插入的情况下,基用例本身的执行也不应受到任何影响。因此,如果我们把上段文字中的两个扩展点拿掉(只看左边的文字)并参照寇本目标用例的标准,可以发现该基用例完全不是一个目标得以完整执行的用例。上述写法是有问题的,它不完整,而且效率不高,似乎模仿了一些编程语言的写法和思路,在实践中不值得推广。
下面再让我们看看寇本版的“使用ATM”[1]:
1. 顾客插卡,输入PIN。
2. ATM验证顾客账户和PIN。
3. 顾客执行下列任一事务:
取款
存款
转账
查询
顾客执行以上事务直到选择退出。
4. ATM退卡。
在这里,取款、存款等事务操作明确地出现在用例的基本流中,显然它们都是被“使用ATM”所包含的用例。注意,在寇本用例中每个动作步骤不一定都是顺序执行的,可以有循环,有选择,甚至可以是任意顺序,例如上面的步骤3。在WEUC中寇本还指出,实际上取款、存款、转账等操作都是顾客执行一次交易事务的特例和具体化,所以还可以进一步画成类似图3的形式。。我们可以看到图1其实是图3的简化。
图 3、更为准确的画法
应该如何判定一个用例关系是包含关系还是扩展关系?有些情况还是比较明确的,例如对于“验证身份”和“吞卡”,大家可能都毫无异议,一致认为它们分别是“使用ATM”的包含用例和扩展用例。但是,一旦出现上例的情况时,就较难处理了。不过,我们通常可以据此判定:如果触发条件中含有基用例负责的事物,即基用例知道附加用例何时、何处、为什么发生,那么基用例应该包含(调用或引用)它;如果触发条件中含有附加用例负责的事物,即附加用例知道它应该何时、何处、为什么发生,那么应该让附加用例扩展基用例[1]。这两条规则还是很管用的。此外,根据笔者经验,还可以参考这样一条简单法则:凡是在用例基本流中出现的附加用例都应作为包含用例,而在扩展流中出现的附加用例必然是扩展用例。显然,图3符合以上规则。
问题似乎得以解决了。然而,在UML 2.0上层结构规范草案(www.uml.org)中,我们却看到了类似图4的方案:
图4、另一种近似的画法
有人要问了,为什么针对同一段用例文本描述,却存在两种矛盾的UML画法,同一个用例“取款”在图3中是包含,在图4中却是继承,到底哪个是对的?其实,图4与图3这两种用例模型在整体上所描述的内容是完全一致的,问题就出在用例名称上。分析、比较用例之间的关系,请务必关注用例的内容——动作步骤。我们可以发现,图4中的“取款”用例与图3中的“取款”用例所包含的实质内容是不一样的,一大,一小。所以,假使我们把它们的名称分别改为“取款交易”和“取款(事务)操作” ,并约定前者“大于”后者,就可以在一定程度上消除二义性,这样两个图就近似等价了。不管如何,图3、图4都一致地没有把“取款”、“存款”、“转账”等用例作为基用例的扩展。笔者认为,经过改进,这两种画法目前都是可行的,而图3可能更好一些。
关于用例包含、扩展和继承关系方面的更深层探讨,值得写一篇专述文章,在这里不可能展开。在目前众说纷纭的情况下,建议大家像寇本建议的那样,如果实在搞不清两个用例到底是什么关系,不如干脆都先定为包含关系,这样做并不影响后续的系统分析设计和使用,因为用例本身的内容写得如何才是问题的实质、真正的关键。总之,实践者不要指望只通过看几个用例的名字就能准确地判断出它们之间的关系。可靠的依据来自于用例内部,不必在弄清用例的关系上浪费太多时间,这个问题可以留待学者和研究人员来解决。
2.4.2 sub use case之争
寇本在WEUC中把包含用例称为sub use case,即subordinate use case之意,但其实subordinate use case(笔者将其译为“分用例”)在亚克申方法中有专门的用途(在亚克申博士早就提出的对大规模系统建模的SystemOf InterconnectedSystems模式中,有超系统/超用例和分系统/分用例之分[4])。而寇本采用的sub use case叫法很容易被直译成中文“子用例”,从而造成新的误解,因为我们知道“父子”一说在OO方法中通常是用来形容对象类之间的继承关系的,子类是父类的派生类,显然这与包含用例的真实语义不符。
在UML[10]中,把包含用例、扩展用例统称为附加(additional)用例,被包含、被扩展的用例叫做基用例,在用例的继承关系中则采用父用例、子用例的说法,这样做是妥当的。
UUCM:
建议在实践中尽量回避寇本sub use case的说法,可以用“包含用例”或“附加用例”来代称,同时明确约定在中文中凡是提到“子用例”的地方,就是指用例的继承或一般化。
2.5 Actor
寇本用例的Actor类型有7种之多,包括[1]:
Actor(something with behavior)、
External actor(an actor outside SuD)、
Stakeholder(an external actor entitled to have its interests protected by the system)、
Primary actor(a stakeholder who requests that the system deliver a goal)、
Supporting/secondary actor(a system against which the SuD has a goal)、
Offstage/tertiary actor(a stakeholder who is not the PA)、
Internal actor(either the SuD, a subsystem or an active component of the SuD)。
RUP关于Actor的定义[7]是: Someone or something, outside the system or business that interacts with the system or business。UML的定义是: An actor specifies a role played by a user or any other system that interacts with the subject。
UUCM:
亚克申用例与寇本用例对于Actor的定义存在着明显区别。亚克申及UML的Actor是系统之外的人或物,而寇本Actor的含义(可能来自早期的亚克申版本)比较笼统,其范围要大得多,有内外Actor之分。既然我们确定Actor的主要目的之一是为了划定系统(或业务)的边界,那么应该始终把Actor当作系统外部的事物,这样才比较妥当,内部Actor是不必要的概念。而且,在实际应用中Actor即重要也不重要[1],识别Actor的主要目的是为了帮助提取用例,通常不需要对各种Actor类型加以如此细致的区分。
另外,寇本关于stakeholder的定义与通常的理解也有所差别。寇本认为stakeholder是一种外部Actor(注:这本身与寇本自己对用例的定义明显存在矛盾[1]),这不对。按常理,所有利益相关人包括内部Actor、外部Actor都应该属于stakeholder之列,尤其当我们讨论的是业务组织的时候。
2.6后置条件
与亚克申用例相比,寇本对用例的后置条件进行了细分,提出了最小保证、成功保证等概念,这样做是有意义的。最小保证描述了系统不管在任何情况下,尤其当用例失败、目标未达成时,都应满足的起码条件和应采取的措施。
UUCM:
建议采纳寇本方法的最小保证和成功保证划分。此外,在前置、后置条件(最小保证和成功保证)中除了说明必须满足的条件外,还可以分别说明系统在用例开始前和结束后的状态,包括各种成功和失败状态以及对失败状态的处理。
2.7动作步骤
寇本用例步骤采用独特的编号方式,基本流采用1,2,3…顺序编号,扩展流的条件和扩展步骤采用数字、字母间隔的方式,如1a、1a1、5c、5c3b1等等,而且还可以使用宏代符*,可以指定任意数目步骤的条件,如1-9a、2,7-9c等等,使用起来非常方便。RUP的基本流、扩展流步骤完全采用自然分节的顺序编号,如1.1、2.3.4.1等等,不便于阅读者找到用例具体的引用位置,在指定扩展位置时显得较为麻烦。
另一方面,RUP用例的每个步骤都可以附上一个名称,这叫做“命名步骤”。
如果一个步骤内容较多,用一个短语标记来概括说明该步骤执行的大致内容,确实比较方便,而且将来需要画用例的活动图时也可以作为快速参考。
UUCM:
建议采纳寇本的步骤编号方式和RUP的命名步骤方法。
2.8文本与UML
亚克申用例方法与UML、RUP三者之间有着天然的紧密联系。用例驱动、可视化建模是RUP的两大特征,若用例和UML缺席,RUP也就称不上RUP了。在亚克申方法中,除了可以用RUP的格式文本描述用例外,还推荐适当地选择利用UML用例图、序列图、协作图、活动图和状态图5种图示从各个角度来描述用例,可谓手段充足、武器齐备。
寇本代表作WEUC的主基调是用结构化/半结构化的文本描述用例。虽然他也提到了UML,但讨论主要集中在如何正确对待UML的用例图和相关CASE工具等问题上,对UML用于描述动态行为的其他4种图的作用和意义强调得不够充分,其实这些图的作用远比用例图要重要得多,也是UML强大描述能力之体现。
UUCM:
如前所述,文本用例本质上是对对象交互过程的执行步骤的罗列。用例本身即每个“椭圆”内部的东西才是最为关键和重要的,用例之间的关系相对来说要次要些,在这一点上,可以说亚克申方法和寇本方法的看法是一致的[1][4]。实践中,我们发现很多时候,先写文本系统用例,后照着已有的文字说明画UML图比先画图或完全依赖于图形来描述系统用例要容易得多。可见对于软件需求分析,我们应该首先把更多的精力放在写好文本用例上(这正是寇本方法的强项)。
但是,寇本认为“Sequence diagrams are not a good form for expression use cases”[1],这种说法有失准确和全面。纵观全书,寇本主要是从工具使用的角度来分析的,他在书中对当时那些不那么先进的CASE工具颇有微词,认为它们不如文本写作更加便捷和有效。然而,事实上这只是问题的一个方面,UML工具的缺陷并不能简单地等同于UML语言本身的缺陷。正确地使用UML及其工具不仅仅是为了获得形象直观、交叉引用、超链接、名称自动变更等一目了然的好处,更重要的一个原因是,通过合适的UML图形,比如SSD(系统序列图),来精确地定义和描述系统事件与作为其响应的系统操作(也就是系统的输入和输出)[8]之间的契约,这正是后续系统分析和设计的起点。序列图在用例分析中其实起到相当关键的作用,在实践中用它来刻画每一个重要的系统用例也是非常普遍的做法。
而且,在分析复杂的业务流程/业务用例时,人们好像更习惯于首先画活动图(可能与人类自身的思维习惯有关),反而不太愿意采用繁琐的文字说明。对于复杂和关键的用例,除了一些必要的文本描述之外,再辅之以UML活动图、序列图或状态图进行可视化,是行之有效的好做法,有助于澄清问题本质、迅速抓住要领。对于复杂的用例模型,通过用例图描述用例之间的关系,提供全局浏览视图,也是非常必要的。
用例的UML图形与文本描述之间不是谁取代谁的关系,而是相辅相成、优势互补,应该因地制宜地加以运用。不仅如此,同时拥有用例的结构/半结构化文
本和UML图形,往往还有助于彼此之间相互比对、确认,能显著提高用例描述和分析的正确性。根据本人经验,把两者结合起来运用效果才是最好的,没有必要过份地强调某一方面。
2.9黑盒白盒
亚克申博士发明的用例实现(UCR,Use Case Realization)[5]在RUP、UML中是一个非常重要的概念,它描述了内部对象如何相互协作共同实现一个用例,理论上每一个用例都应该至少有一个UCR与其对应,因而UCR在亚克申方法中起到了联接问题域和解决域、贯穿整个软件分析设计过程的关键作用。在寇本方法中,不存在UCR这个术语,只有黑盒用例(需求)、白盒用例之分(需求的实现)。
UUCM:
首先,既然谈及基于用例表示的功能需求,那么它就应该是黑盒的、透明的。如果我们看到了系统内部的情况(白盒、不透明),那么这其实已经是需求的一种实现了。所以,我们应该在需求分析时尽量避免“白盒用例”这种矛盾的说法。严格地区分UC和UCR,有助于项目团队在实践中消除需求和实现不分的情况。这一点过去在被拉来写需求的程序员当中比较普遍,受习惯性思维的影响,他们往往写到最后就变成写软件设计方案了,这是很糟糕的。
2.10格式模板
寇本在WEUC中一共列出了5种主要的用例格式模板:完整型、简易型、单列表式、双列表式和RUP样式。在此,我们推荐以完整型(寇本本人最喜欢的)为基础,结合了单列表式和RUP样式特点的UUCM模板:
用例名称:
层次:
+ | ! | –
范围:
简述/背景:
主使用者及利益:
其他受益人及利益:
受益人1:
受益人2:
最小保证:
状态1:
状态2:
后置
条件
成功保证:
前置条件:
条件1:
条件2:
状态1:
状态2:
触发事件:
基本流:
1. 步骤1
2. <可选名称>.步骤2
…
n. 步骤n
<结束>
扩展流:
1a. 条件1:
1a1. 步骤1
1a2. 步骤2
扩展点:
名称1:位置1
名称2:位置2
技术和数据变化:
1a.
2a.
非功能需求:
业务规则:
备注:
其他必要字段
……
表1、UUCM模板v1.0
双列表式较多地被用来描述用户界面需求,有些人偏爱它,但我们发现双列表不够简洁,比较占空间,而且很多情况并不适用,比如参与者多于两个的情况。
三、结语
寇本用例方法以基于目标的结构化/半结构化文本描述见长,亚克申用例方法更重视UML可视化建模和用例驱动过程。两者尽管同宗同源[1],却在一些使用细节上存在着明显差异,而且各自还在沿着既有轨道继续向前发展。 本文提出的统一用例方法并不是一种全新的方法,UUCM仅仅是个符号或代称(也许可以有其他更好的名称),它实质上代表了一种解决方案和思路,目的是吸收亚克申和寇本用例方法的长处,消除两者的不一致,从而帮助实践者尽可能规避使用上的误区,发挥用例和UML方法“1+1〉2”的联合优势。这既是实践的选择,也是现实的需要。
话说天下IT之势,合久必分,分久必合。UUCM不是句号,而是一个新的起点。出于商业、私人或其他方面的原因,国内外许多技术流派分呈的局面会长久持续下去,这本身是一件好事。不过,对于我们实践者来说,选择实用的工程技术时不应有门派分割的障碍。对于特定的场合、特定的项目,企业人往往只有一个明智的选择,那就是:用最小的成本创造最大的客户价值。所以,对于实用型技术我们完全可以采取拿来主义的态度,防止guru-locked-in,适用的即是最好的!
致谢
感谢邱嘉文(从他这里我学到了“胚”这个词)、潘加宇、沈备军博士在百忙之中审阅了全文,并提出了宝贵的改进意见!
参考文献
[1] Cockburn A.著,《编写有效用例》(英文版),机械工业出版社,2002年7月。
[2] Cockburn A., Using goal-based use cases, JOOP Vol. 10, No. 6 (Sep-Oct), No. 7 (Nov-Dec), 1997.
[3] Jacobson I.等著, Object-oriented Software Engineering: A Use Case Driven Approach(修订版、英文版),人民邮电出版社,2003年9月。
[4] Jacobson I.著,程宾等译,《统一软件开发过程之路》,机械工业出版社,2003年8月。
[5] Jacobson I.等著,周伯生等译,《统一软件开发过程》,机械工业出版社,2002年1月。
[6] Hurlbut R., A Survey of Approaches For Describing and Formalizing Use Cases, Expertech, Ltd., 1997.
[7] Kruchten P., The Rational Unified Process An Introduction, Second Edition, Addison Wesley, 2000.
[8] Larman C.著,姚淑珍等译,《UML和模式应用:面向对象分析与设计导论》机械工业出版社,2002年1月。
[9] Leffingwell D.等著,蒋慧等译,《软件需求管理:统一方法》,机械工业出版社,2002年3月。
[10] Rumbaugh J.等著,姚淑珍等译,《UML参考手册》,2001年1月。
[11] 邵维忠等著,《面向对象的系统设计》,清华大学出版社,2003年2月。
[12] 张恂,《让历史告诉未来:评Ivar Jacobson博士的〈用例的昨天、今天和明天〉》,IT之源,2003年4月。
[13] 张恂,《如何写好最外层用例》,IT之源,2003年3月。
近期评论