`
hzqz
  • 浏览: 4275 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论
阅读更多

Susan Lilly 著,qian_x_j

 

无论是你的系统边界是模糊的,还是你在用户接口中的用例被搞得混乱,你很快会发现你一开始建模时会很容易趋向于一些相当可预见的问题领域。不过你走运了,这也很容易避免。

 

 

用例是一项日益流行的技术,用来文档化系统和软件的需求。凭借它们简单的图形符号和接近自然语言的规格定义,用例对开发团队颇具吸引力——甚至那些对常规需求规范经验甚少的团队也是如此。然而,这个简单是有欺骗性的。虽然开发项目的团队使用用例,一开始没有遇到大麻烦,但是许多团队在较大的场合下应用用例时,会遭遇到相似的问题。

虽然从实践中学习可能是件好事,但是这在商业世界里却是昂贵的教育方法。你的项目团队不必要亲身经历这10个最常见的陷阱。我有四个建议,可以帮助避免许多常见的用例陷阱,并且其中有一个将帮助你发现并且移除陷阱。

 
 

用例的前10个陷阱

 

1.系统边界模糊或者变化无常。

2.用例描写来自于系统(并非角色)的观察点。

3.角色名称互相矛盾。

4.过多的用例。

5.角色和用例的关系连接象蜘蛛网一样(复杂)。

6.用例规格叙述过长。

7.用例规格叙述混乱。

8.用例没有正确描述功能。

9.用户不可理解用例。

10.用例从来不会结束。

 

来自于Lilly, S., 用例陷阱:在实际项目中使用用例的前10个问题,TOOLS USA '99,IEEE计算机社学报,1999

 

 
 

 

 

 

 

 

 

 

 


[1]系统在哪儿?(系统边界)

要清楚系统边界。用例模型具有直接的符号。在它的最简单的形式中,它仅仅是一个标志性的盒子来描述系统边界,而角色(棒人形)画在盒子外面,用例(椭圆形标记)画在盒子里面。线和箭头连接着角色和用例。

但是我们称为系统的盒子是什么呢?我们是在谈论计算机系统么?是一个应用程序?是一个子系统?抑或一整个商业企业?用例可以合理地描述这些任何的系统边界,但是它们应该在一个时间里只注意一点。特定的角色和用例对某个系统边界是恰当的,却很可能对另一个不同的系统边界是不正确的。

让我们看看一个棒球订票系统的例子吧。一个亭售用户(售票亭买票的客户)使用计算机来订票,或者一个电话用户拨打电话号码800来进行这次票务生意,而电话员(一个售票业务的雇员)使用计算机系统来订票。谁是角色呢?在混合系统边界的用例图中,建模者试图在同一个用例图中同时体现业务用户和计算机用户。订票用例的文本规格定义也变得混乱:因为电话用户和业务的交互的集合是跟其它角色和计算机系统的交互的集合是不同的。

边界的不明确或者矛盾(陷阱1),可能是在我所观察过的许多第一次使用用例的项目中,最普遍的问题。当系统边界被搞乱了,你就很难知道要输入什么,要输出什么。你的工作可能会由于以下情况而终止:

。过多的用例(陷阱4)。

。角色和用例的关系混乱(陷阱5)。

。庞大的,却又混乱的用例规格定义,尝试描述多个范围层次(陷阱67)。

。用例不能终止,因为你的团队试图让“整个大洋燃烧起来”(尝试分析每件事情)。

 


这些问题可以通过明确范畴并标出系统边界来避免。比如,系统边界可以描述为计算机系统,亭售用户和电话员作为订票用例的角色。或者,系统边界可以描述为整个企业。电话用户作为角色,是一个售票业务的用户,但并非计算机系统的用户。两者都是合理的模型;如何选择它们之中的一个,取决于你正试图定义计算机系统需求,还是在业务过程建模或重构中使用到的用例。

一个相关的问题是,整个系统的边界丢失。这种问题经常发生在用例模型使用可视化建模工具(比如 Rational Rose,市面上面向对象建模的头号工具)上,它们不允许在用例图中放置边界盒。

如果你正在使用类似的工具,你仍应该努力使系统边界明确。即使它(边界)并不在图上,它也应该在你的脑子里。在图上放置角色和用例时,要假象那个盒子在那里。

 


 

 [2]模板

为你的用例规格说明使用一个标准化的模版。虽然用例符号已经成为面向对象管理组织的统一建模语言(UML)中的标准,但用例的自然语言规格却没有。若想要在你的工程中成功的书写用例规格说明,为它们创建一个模版吧(当你真正需要使用它时就更适合了)。模版提供了用例和鼓励坚持项目标准的可靠性。

由于缺乏工业标准,许多相似的领域集里的用例规格模版被提议。用例名(Use Case Name,就是出现在用例图中椭圆形下面(或者里面)的名字。角色(Actor就是启动用例的主要角色。从对于主要角色或角色们的观察来看,目标(Goal就是用例目标的一个简洁描述。当触发器(Trigger作为具体事件导致用例启动,在用例应用中的环境(Context就是背景“故事”了。正常流(Normal Flow包括几个步骤,它们描述在角色和系统之间通常发生的最典型的交互序列。变体流(Alternative Flows是正常(可成功的)流的变体路线,每一个都描述了它的触发条件(是什么导致从正常流跳入),过程和结果。异常流(Exception Flows是错误的路线,每一个都描述了它的触发条件(是什么导致从正常流跳入),过程和结果。还有一个可选的问题领域是,指出所有的假设前提,就是用例是基于什么的。至少,用例规格应该回答这些基本问题:

       。谁?(角色)

       。为什么?(目标和/或环境)

       。何时?(触发事件)

       。什么?(正常流)

       。还有什么?(变体流和/或异常流)

另外,对于在每个用例中的定义域,定义一个标准也很有帮助,那些信息是要为一个小组,或者一个相关用例的“包”而说明的。这些信息应该包括角色名和其它重要术语的术语表(防止陷阱3),还包括交叉用例的业务规则,一个“故事”(或者动态图(active diagram))显示用例在时间过程中的关系,还有其它等等。

在我的公司,我开发了微软word形式的模版来定义用例包,具有自定义风格的主要元素及其帮助说明。你如果想要把基于word的文档自动的导入需求管理工具,自定义风格(word)是非常有用的。内建的帮助说明旨在方便那些用例书写者,因为他们不愿意在写文档时回过头去察看项目标准或者过程要点。它提供了,符合用例命名惯例的提示语(比如,以“action”动词开头的短语),规格定义规则(比如,使用主动形式的主谓句;避免逻辑分支),还有实用的提示。

设计一个工程的用例模型,你不必从打草稿开始;你可以从网上获取例子并且裁剪它们。Alistair Cockburn 有一个网址(http://members.aol.com/acockburn/papers/OnUseCases.htm),那儿提供了很多有用的用例支援,包含了用例模版,有HTML形式,微软的Word形式和文本形式。

[3]观察点(目标,而非琐碎的东西)

注意目标。在外观察以上来看,基于用例的需求对于传统的系统需求(比如,“Shalls”)的最大差异是棒人形了。这代表的意义并非完全是它的样子所要描述的,它旨在强调规格化系统要基于已定角色(人类用户和其他扩展实体)的观点。在面向用例的世界观里,系统的存在是因为,角色有一些让它们使用而满足的目标。我们书写用例,是要指出角色和系统之间交互的本质,结果就是角色目的满足。(Ivar Jacobson,用例之父,使用术语“值的结果(results of value)”来暗示在用例中考虑角色的真正需要或者目标的重要性)

把这一点牢记在心,我们应该能够扫视用例模型,并且列举那些在用户使用系统中想要做的事。这些并非是琐碎的用户的交互,而是真正的目标。选择那些反映附带的行为,而不是真正的角色目标,会导致过多的用例(陷阱4),并且导致用户的问题表述同基于用例的需求规格的脱离。

所以,要选择好的用例,就要注意那些反映角色的真正的目标。然后,从角色角度命名用例,而不是系统角度。

比如,“处理订票”和“显示比赛安排”是系统要做的,所以不是好用例名。“订票”和“察看比赛安排”是系统用户的目的,这才是好的用例名。

另外一个用户目标获取的迷失具有讽刺意味,某些建模者期望于用例“面向对象”。这种情形的症状是,存在臃肿的“CRUD”用例,那包括了所有的对于业务对象可能的行为。(“CRUD”是对象创建(Create),读(Read),更新(Update),删除(Delete)能力的首字母。)这些用例经常包含的名字有“维护”(“maintain”),“管理”(“manage”)或者“处理”(“process”)。

CRUD用例有什么错呢?第一,也是首要的,它们经常不是直接的相关于角色目标。它们经常描述许多角色目标的联合体,来自于多个业务环境和过程,由于许多目标共享一个对象而被组合在一起。CRUD用例还有什么错呢?它的规格定义是典型的过于冗长(陷阱6),它经常会关联过多不同的角色(陷阱5)并且这些角色对于整个用例的“功能定义”是典型的令人怀疑(陷阱8;还有其它)。简言之,当我们运用面向对象方法分析时,很多时候我们要注意于对象,但是选择用例本身作为对象并非恰当。

不要把用例规格定义同用户界面设计混淆起来。有一个流行的观点,就是:因为用例有关于角色和系统之间交互,所以把用户界面放到用例规格定义中去是个好主意。粗粗一看,屏幕快照好像很有用,因为它们在规格定义中描述了角色/系统交互。

然而,坏处远大于好处。假如我想要使自己掉入了陷阱10(“用例从来不会结束”),我可以把屏幕快照(界面)放入我的用例规格定义中。这儿有个我观察过的项目,曾经这样做:用例,试图定义系统操作需求,并且完结于包含系统的用户界面设计。一旦需求需要被核准并且被定为基准;这些设计元素,很自然的,还是要被更改。所以用户还是不能停止制作需求文档,因为它包含了已经完成了的用户界面设计,错误的和/或矛盾的。

即便是用例已经被核准,它会在短期内是成功的(短期维持)。然而用户界面设计很可能随着时间而需要更改。我们不想把系统需求依赖于设计。这种依赖应该用其它方式解决——用户界面设计必须满足用例需求。

在把界面放入用例的工程中,我还见到过其它问题。为了尝试反映在用例与屏幕之间一对一的通信,他们选择了反映大量用户界面而非用户目标的用例。(典型的,用户目标比用户屏幕“更加”值得交互。)他们试图通过使用内建用例关系(“使用”或“扩展”),把大量的界面用例揉合到完全的用户目标中去。这样就导致了在例用模型中,形成了关系蜘蛛网,过多的描述了用户界面的切换,而忽略了用户目标和功能定义。用户界面切换图是一个有用的系统文档;然而,它是属于用户接口(设计)文档,而非用例(需求)文档。

一个更好的方法是,让用户接口细节和用例交互松散的耦合。一点点的耦合是合适的;包括“低分辨度”的用户界面图片,用于理解用例。但是不要过分的把功能定义同用户接口(UI)机制结合起来。用户接口更容易发生更改。在规格定义中,注重于建立角色要做什么(比如,“选择一个游戏”,“提交一个请求”),而非怎样交互(比如,“双击提交按钮”)。

另外,不易被发现的问题是,试图在用例和用户接口之间通信可能导致不正确的功能定义(陷阱8)。

比如,若我们声称很多用户能够使用赛程安排界面来察看赛程,但是通过适当的验证,一个用户(比如,赛程管理员)还可以使用那个界面更新赛程安排。建模者决定把察看和更新功能组合到同一个处理赛程的用例,基于公共的赛程用户界面。

这个用例跟只能察看界面的角色关联,当然也跟能够更新的角色关联(也许是一个变体流)。这个结果是不正确的功能定义。只要看看这个模型,它呈现的是,亭售用户可以察看并且更新赛程,如同赛程管理员能做的一般。分离各个用例,要基于实际的用户目标和功能定义,而非组合基于用户接口,这样才会得出正确的模型。

 [4]经常检查(复查)

复查你的用例图和规格定义。假如你不能防止所有的陷阱,你至少能够尽可能早的截取问题并且修正它们。这个主意并不是新的并且迷人的。由这种经典的方法,进行代码走读已经经历了25年了,而且相当于这种复查过程的应用,在成熟度模型等级3Capability Maturity ModelsCMM Level Three)中是一个关键的过程。

怎样把它应用到用例呢?在我们公司的项目中,应用多层通过的复查过程,导致了好的结果。首先,用例图的复查是,通过察看用例规格定义的简略的存根(仅仅是用例名及其目标或者简单描述)。

在对于用例规格定义进行细化以前,对于草图,这种复查进行的越早越好。对于草图复查以后,由于图是正确的,用例规格定义的细化便可顺利完成了。然后,执行最终的用例图及其规格定义的复查。

我们发现两阶段复查过程要优于一次“大的”复查。在书写规格定义细节上投资许多时间以前,用例图中大量的组织性问题被揪了出来。当用例图需要重新组织时,这种方法缩减了必须做的重复工作的总量。

使用例复查有效的其它窍门:

。使用复查校验表来帮助发现常见的用例问题。

。描绘原素材来“讲一个故事”。有时候,描绘图形素材,要比平实的文字要吸引人。我们建议列出一个“广度优先”的概览,然后是若干小组深入的相关的用例。比如,描述者可以概述用例图的一部分,它是相关于一个角色或者一个特定的业务过程;然后通过细节遍历这些规格定义,然后回到用例图,考虑用例集合的另外相关的部分。但是永远不要把按字母排序作为描述的策略!(是的,我真的看到过有人这样做)

。在最初的模型复查时,考虑使用非常规的复查技术。我喜欢使用“黄色粘纸墙上复查(Yellow Sticky Wall Review)”的方法(名称来源于几年以前在IBM对象技术大学中的经历),对非常规的图形模式进行复查。用例图被打印出来,贴在进行复查处的墙上。复查者在黄色粘纸上写上他们的注解,把纸贴在用例图上模型附近合适的部位。

常见的错误

我所描述过的陷阱并非对用例的控告;应该说,对于那些从来没用过它们的初用者来说,它们是典型的困难;并且多数应用用例的开发团队确实存在新手。

 

此外,用户,共同参与需求分析的最终使用者和领域专家们,一般没有使用用例经历。由于建模符号的简单,并且是自然语言的规格定义,所以很容易上手。

然而,简单的形式不应该掩盖一个真相,就是需求分析和定义并不是次要的工作。很多团队在初次尝试用例时遭遇了相似的陷阱。

这些建议能够帮助你的团队避免这些问题。

链接:http://www.umlchina.com/xprogrammer/issue/5/avoidusecasepitfalls.htm

分享到:
评论

相关推荐

    用例分析技术(原书第二版)

    这些深入的讨论有助于读者避免常见的陷阱,提高用例分析的质量和效率。 #### 6. 多角度解读用例 《用例分析技术》一书不仅仅局限于技术层面的讲解,还从用户视角审视系统,讨论了边界、接口和系统范围界定等关键...

    C语言基础测试用例

    这些测试用例通常包括各种常见问题和陷阱,例如数据类型、运算符、控制流程、函数、数组、指针等。 在描述中提供的链接 "http://blog.csdn.net/kaige2111/article/details/50939163" 是一篇中国软件开发网络(CSDN...

    动态规划测试用例.rar

    压缩包中的"readme.pdf"可能是对测试用例的详细解释,包括如何使用它们、预期的输入输出格式以及可能遇到的陷阱。阅读这份文档是非常重要的,因为理解测试用例的设计可以帮助我们更好地理解和评估我们的代码。 "exp...

    自动化测试用例exe

    ErrorDemo则可能是错误演示,它可能包含了常见的编程错误或者测试陷阱,供学习者参考,以便了解和避免在实际测试中可能出现的问题。 使用CodeUI进行自动化测试时,首先需要创建一个测试项目,并在其中添加测试类。...

    VC6.0++程序用例

    通过深入研究这些【VC6.0++程序用例】,你不仅可以提升你的编程技巧,还能了解到C++编程中的一些最佳实践和常见陷阱。同时,你还可以了解到如何利用VC6.0的IDE进行项目管理、编译和调试,这对于成为一个熟练的C++...

    how to avoid use case pitfalls

    在进行用例分析时,如何避免陷入常见的陷阱是软件开发中的关键问题。用例作为一种记录系统和软件需求的流行技术,其简洁的图形表示和易理解的自然语言规范深受开发团队喜爱。然而,这种简单性也可能导致误解,尤其是...

    snmp++简单用例

    通过创建一个`TrapSession`对象,你可以设置监听端口和社区字符串,以便接收设备发送的陷阱(Trap)通知: ```cpp TrapSession trapSession("162", "public"); // 162是默认的Trap端口号 trapSession.add_trap_...

    MySQL数据库源代码学习研究(包括代码注释、文档、用于代码分析的测试用例).zip

    此外,注释还可能揭示一些优化技巧和陷阱,有助于提升我们的编程能力。 文档部分则为学习MySQL提供了理论基础。这可能包括设计文档、架构概述、开发者指南等,帮助我们从宏观上把握MySQL的整体结构和设计理念。例如...

    hibernate-testcase:Hibernate测试用例存储库

    10. **最佳实践**:通过测试用例,开发者可以学习到在实际项目中使用 Hibernate 的最佳实践和常见陷阱。 通过深入研究和运行这个 "hibernate-testcase" 项目,开发者不仅能了解 Hibernate 的基本用法,还能掌握如何...

    使用模型检查优化测试用例生成的实现框架

    然而,在测试用例生成的过程中,冗余的“陷阱属性”会导致频繁调用模型检查器并生成冗余的测试用例。本文提出了一种基于可满足性求解(SAT求解器)优化测试用例生成的实现框架。在生成新的测试用例后,使用SAT求解器...

    Writing Effective Use Cases-- Alistair Cockburn

    即使初次接触用例撰写,也能通过本书的引导,逐渐掌握技巧,提高效率,避免常见的误区和陷阱。最重要的是,Cockburn鼓励大家放松心态,写出易读且有意义的文档,这本身就是对组织的一项重要服务。

    error-prone,将常见的Java错误捕获为编译时错误.zip

    这些规则针对常见的编程陷阱,如空指针异常、未初始化的变量、不安全的类型转换等进行检测。当代码违反了这些规则时,error-prone会在编译过程中报错,而不是等到运行时才暴露问题,这极大地提高了开发效率。 使用...

    如何画用例图?用例图解析

    正确理解和使用用例图,可以避免功能分解的陷阱,确保系统设计紧密围绕用户价值,提供更好的用户体验。在构建用例图时,要始终关注参与者的需求,通过整合相关功能来体现系统的整体价值,而不是只关注零碎的功能细节...

    Python技术使用中的常见陷阱与解决方案.docx

    通过深入理解这些陷阱背后的原理,可以有效地避免错误,提高代码的质量和稳定性。在实际开发过程中,建议: - **代码审查**:定期进行代码审查可以帮助发现潜在的问题。 - **单元测试**:编写单元测试用例,确保...

    内存泄漏:Python中的隐蔽陷阱与应对策略

    - **测试**:编写测试用例来检测内存泄漏,尤其是在长时间运行的应用程序中尤为重要。 #### 结论 通过本文的详细介绍和示例代码,我们深入了解了Python中的内存泄漏问题以及避免它们的方法。内存泄漏虽然可能不易...

    datasource-test-bff:Apollo Server具有用于不同用例的各种数据源,包括REST,SQL,MongoDB和CosmosDB。 与Knex和Objection ORM集成以进行SQL查询

    该方法的陷阱架构优先锅炉板更多。 当我们想用Objection添加一个新模型时,我们将不得不创建graphql类型以及类本身,而不是为我们生成模式的代码。 由于我们类型的多个事实来源,因此有可能造成不一致。对于Cosm

    非程序员2001-5

    - **避免用例陷阱**:讨论了在使用用例模型时常见的误区及其解决方案。 - **使用UML设计数据库应用**:详细讲解了如何运用UML进行数据库应用程序的设计。 - **统一变更管理的威力**:介绍了统一变更管理的概念和其在...

    IT软件测试技术资料.docx

    - 向有经验的测试人员学习:这强调了学习和交流的重要性,新进测试人员可以从前辈的经验中获益,了解最佳实践和常见陷阱。 - 阅读软件测试的相关书籍:阅读专业书籍可以帮助理解测试理论、方法和工具,提升测试...

    代码走读[总结].pdf

    设计模式可以帮助我们避免陷阱或从特定陷阱中恢复,一种方法是描述了经过实践证明的成功的设计技术,可以用上下文相关的方法定制它们,以适应新的设计情况。 在设计模式和重构之间也存在着紧密的关系。设计模式可以...

Global site tag (gtag.js) - Google Analytics