开始复习用例图之前,我先花点时间把话放这儿:软件工程这门课,考来考去无非就是需求、设计、测试和过程管理这几座大山。而用例图这个东西,看着简单,画起来也快,但真要拿高分,大多数人会死在细节上。比如参与者和用例分不清、包含关系和扩展关系方向搞反、系统边界画错,这几板斧下来,十几分就从手里溜走了。这篇笔记是我把教材、软考真题和课程设计经验揉在一起整理出来的,核心目标只有一个:让你不仅会看用例图,还能自己从一段乱七八糟的需求描述里,把用例图准确、规范地画出来,同时应付期末考试和软考中级软件设计师的选择题与案例分析题。
软工复习笔记:用例图,从画对到讲透
1. 用例图解决的是“系统到底该干什么”
很多同学第一次接触用例图,会把它当成一种画图工具来学,这其实是用反了。用例图是一种建模语言,是UML里专门用来表达功能需求的视图。它的本质是回答一个问题:在这个系统里,谁能用系统做什么。你可以把它理解成一份系统功能的“说明书”,只不过这份说明书用的是图形符号,而不是文字段落。相比文字需求文档,用例图最大的优势在于整个系统的功能边界一眼就能看全,所有参与者与功能之间的关系也清清楚楚。
1.1 为什么需求分析阶段最需要用例图
软件工程里有一句老话:需求阶段犯下的错误,修复成本是编码阶段的几十倍。很多项目做到一半发现需求理解不一致,追溯回去,绝大多数问题都出在“用户表达不清楚”和“开发理解有偏差”之间。
用例图恰好解决了这个鸿沟。它把参与者(人也好、外部系统也好)和系统提供的功能(用例)放在一张图上,双方坐下来对着图讨论:这个角色能不能做这件事?这件事做完后有什么结果?边界在哪?可以通过一种符号语言,把“模糊的描述”变成“确定性的功能条目”。这也是为什么软考中级软件设计师的考试里,用例图总是作为重要的数据库/需求分析案例反复出现,图书管理系统、网上书店、学生选课系统这类题目年年都有。
1.2 用例图在UML全家桶中的位置
UML一共提供了14种图,分结构图和行为图两大类。用例图属于行为图中的一种,而且是行为图的起点。为什么叫起点?因为一个软件系统的建模,通常从用例图开始:先弄清楚系统对外提供哪些功能,再根据这些功能去设计类图、时序图、活动图,最后落到代码实现。
你可以把用例图当成软件工程的“户型图”——建房之前先画户型图,确定哪里有客厅、哪里有卧室、哪里是厨房;用例图就是确定系统的功能分区。如果户型图都没画清楚就开建,后面砸墙改管道的成本可就大了。学习时建议把用例图放在需求分析阶段来学,而不是孤立地当作一个绘图知识点。
2. 四大核心元素:看懂用例图的第一步
用例图的图形元素不多,但每一个都有严格的语义。很多复习资料上来就让你画,却不解释元素背后的判定标准,结果就是画出来的图“形似而神不至”。这四大核心元素是:参与者、用例、关系、系统边界。
2.1 参与者:不是“人”这么简单
参与者,英文叫Actor,在UML里用人形图标表示。这里最容易犯的错误是:把参与者等同于用户。实际上参与者的定义是“与系统交互的外部角色”,可以是人,也可以是一个外部系统,还可以是硬件设备或时间触发源。
判断一个角色是否属于参与者,有一个很实用的标准:看它是否直接与系统交互,并且是否有独立的目标。“顾客”是参与者,因为他在图书管理系统中要借书、还书、查询;“图书管理员”也是参与者,因为他要处理借还登记、管理图书信息。但如果只是“顾客的家人”,他不直接操作系统,那就不能出现在用例图中。
另一个常被忽略的考点:参与者之间可以有泛化关系。比如“教师”和“学生”都是“用户”的泛化子类,在用例图中用一个空心箭头表示继承关系。这种关系在考试中偶尔会出现,用来表达子类参与者可以做什么父类能做的功能,同时又有自己的特有功能。
2.2 用例:功能的“黑盒”描述
用例用一个椭圆表示,里面写功能名称。别小看这个命名,考试判卷时用例名称写得好不好,很可能就是1到2分的差距。规范的用例命名应该采用“动词+宾语”的结构,例如“借阅图书”“查询图书”“缴纳罚款”,让人一看就知道这个功能完成什么操作。不规范的命名包括“图书借阅处理”“数据库操作”这类模棱两可或太偏内部实现的描述。
这里要理解一个关键点:用例描述的是一个可见的功能结果,不是系统内部怎么实现的。具体用“黑盒”的说法来解释,就是用户关心的是“我借到了书”,而不是“你用什么SQL语句把库存减了”。你在设计用例时,要站在参与者的视角,问自己:这个角色通过这个功能,获得了什么可观察、可验证的价值?如果回答不上来,这个用例很可能是个伪用例,或者说它其实是另一个用例的内部步骤。
2.3 关系的三兄弟:包含、扩展、泛化
用例图中的关系是考试的重灾区,尤其是包含关系(include)和扩展关系(extend)的使用。很多人记不住区别,或者画的时候方向画反,这些都是典型的丢分点。
包含关系用虚线箭头加<<include>>表示,箭头从基础用例指向被包含用例。它表达的是:基础用例执行过程中,一定会调用被包含的用例,被包含用例是基础用例的必要组成部分。典型例子:图书管理系统里“借阅图书”这个用例,一定会包含“验证读者身份”这个步骤。所以从“借阅图书”画一条带<<include>>的虚箭头指向“验证读者身份”,表示每次借书都必须验证。
扩展关系同样用虚线箭头加<<extend>>表示,箭头从扩展用例指向基础用例。它表达的是:在某些特定条件下,基础用例会“延伸”出扩展用例的功能,但即使没有这个扩展,基础用例也能独立完成。典型例子:“借阅图书”在读者已经借满限额时,会执行“处理借阅超限”这个额外流程。这时“处理借阅超限”扩展了“借阅图书”,箭头方向从扩展用例指向基础用例。注意箭头方向一定是从扩展用例指向被扩展的基础用例,很多同学画反,拿到卷子才发现少了两分。
很多同学分不清包含和扩展,我提供一个通俗记忆法:包含是“每次都要做”,扩展是“特殊情况才做”。也可以这样理解,包含关系去掉被包含的用例,基础用例就不完整;扩展关系去掉扩展用例,基础用例依然完整。
泛化关系表达的是“继承”的意思,用在用例与用例之间时,子用例继承父用例的所有行为,同时可以增加自己的行为或覆盖父类的部分行为。比如“缴纳罚款”可以进一步泛化为“现金缴纳罚款”和“在线支付罚款”。泛化关系在考试中考查频率不如包含和扩展,但也是需要掌握的内容,尤其在设计模式与面向对象结合出的考题里可能会隐形出现。
2.4 系统边界:把“内”和“外”切开
系统边界在用例图中通常画成一个矩形框,用例放在框内,参与者放在框外。这个矩形框表达的是系统的功能范围:凡是框内的都是系统要做的,凡是框外的都是外部角色和外部系统的职责。
这个看起来很简单的元素,其实暗藏考点。有时候题目故意让你判断某个功能该不该放进系统边界内。判断标准就一条:这个功能是否由系统自动完成,是否属于系统自身的职责。比如“图书入库登记”是系统功能,放进框内;“图书采购决策”如果是靠人工判断、不在系统内实现,就不能放进框内。考试时如果拿不准,可以换个问法:离开这个软件系统,这个功能还能完成吗?如果人工也能完成,那它可能就是业务环节而不是系统用例。
3. 从需求到用例图:手把手建模步骤
画用例图不是想到哪画到哪,我有自己的一套固定流程,复习和考试都用它。这套流程以图书管理系统为例展开,这是软考和课程设计里最经典的案例,吃透这个例子,其他系统都是换汤不换药。
3.1 第一步:识别参与者,先列全再筛选
拿到一段需求描述,第一件事是把所有出现的人、角色、外部系统全部列出来。以图书管理系统的经典需求为例:
- 读者:查询图书、借书、还书、续借、缴纳罚款
- 图书管理员:处理借书登记、还书登记、维护图书信息、维护读者信息、处理罚款
- 系统管理员:管理管理员账号、备份数据
- 外部系统:校园一卡通系统(用于身份验证)、图书ISBN数据库(用于获取图书元数据)
这里很容易踩的坑是:把所有角色都当成参与者,结果图上一堆人形图标。比如“财务处”如果只是接收罚款报表,不直接操作系统,就不应该出现在用例图中;“时间”虽然出现在“定时备份”功能中,但如果系统是由触发器自动启动备份,那时间实际上触发了用例,可以当作一个外部参与者。
我的建议是第一轮先把所有候选角色写出来,第二轮逐一质问:这个角色有没有直接操作系统?有没有独立的使用目标?如果答案是“没有”,就把它划掉。筛选完,剩下的就是真正的参与者。
3.2 第二步:识别用例,把动词短语变成功能条目
识别用例最有效的方法,是给参与者分配“动词短语”。你可以问:读者在这套系统里能做什么?回答往往是“查书”“借书”“还书”“续借”“交罚款”。把这些动词短语规范化,就得到了用例。
但这个环节有个细节容易被漏掉:多个参与者可能共享同一个用例。比如“借书”不仅是读者的行为,也是管理员的操作前提,读者借书后管理员需要登记借阅信息。在用例图中“借阅图书”这个用例只需要画一次,可以同时被读者和管理员两个参与者连接。我见过不少初学者在图上画两个一模一样的“借书”用例,分别挂给两个参与者,这完全是多余的,而且会扣分,因为用例是系统的功能,不是某个角色的私有动作。
还需要注意划分用例的粒度。粒度过粗,一个“管理”用例塞进了增删改查所有操作;粒度过细,连“输入用户名”“点击确认”这种操作步骤都画成用例。这两种极端都是考试中常出现的送分题陷阱。正确做法是:一个用例对应一个完整的、可交付的功能结果。“新增图书”“删除图书”“修改图书信息”适合拆开;“图书管理”则太粗,不符合用例定义。
3.3 第三步:梳理关系,先找出必做项,再找出可选分支
用例和参与者之间的关系叫关联关系,画成实线,这是最基础的一层。除了关联关系,用例与用例之间还有包含、扩展、泛化三种关系。梳理顺序很关键:
先把“每次都会重复执行”的公共步骤抽出来,看看是否有多个用例都能用到的通用流程,如果有,就用包含关系指向它。在图书管理系统中,“验证读者身份”就是一个公共步骤,不但“借阅图书”会用到,“续借图书”“缴纳罚款”也可能需要,所以可以独立成一个用例,让多个基础用例包含它。遇到这种情况,不要在每个基础用例里都画一个“验证读者身份”的椭圆,应该抽出来,避免重复并体现设计思想。
然后找“条件触发”“可选的”分支流程,用扩展关系表达。还是图书管理系统的例子,“借阅图书”时如果读者卡过期,系统要执行“处理过期读者卡”流程;如果借阅册数已满,要执行“处理借阅额度超限”流程。这些分支不是每次都会发生,但它们扩展了主流程,所以用扩展关系。
再判断是否有用例存在相同的行为结构,可以考虑泛化关系。比如“查询图书”用例可以泛化为“按书名查询”和“按作者查询”,如果这两种查询方式系统处理逻辑差别不大,通常不建议用泛化;如果差别明显,比如按分类浏览和按关键词检索走的完全是两套逻辑,泛化就有意义了。软考题目里泛化关系考得不多,但一旦考到,基本是送分题,识别出“父用例-子用例”的关系就行。
最后一步检查包含和扩展的方向。包含关系箭头指向被包含的公共用例;扩展关系箭头从扩展用例指向被扩展的基础用例。我的检查口诀是:“包含箭头指向公用,扩展箭头指向基础”。虽然简单,但应付判断题足够了。
3.4 第四步:绘制与评审,在考试中就是“画框、排布、连箭”
考试画用例图不需要漂亮,但需要规范。我的绘制顺序是:
- 先画系统边界矩形框,所有用例放在框内,参与者放在框外。
- 再画用例椭圆,尽量让框内布局分布均匀,避免箭头交叉过多。
- 然后画参与者,放在系统边界外,建议人形图标朝内,可以贴进边界处。
- 最后连接关联线、包含线、扩展线。
上考场前,务必记住这些符号的标准化画法:
- 参与者:人形图标,下方写角色名。
- 用例:椭圆,内写用例名。
- 系统边界:矩形框,左上角写系统名。
- 关联关系:实线。
- 包含关系:虚线箭头加
<<include>>。 - 扩展关系:虚线箭头加
<<extend>>。 - 泛化关系:带空心三角箭头的实线,从子指向父。
画完之后做两轮自查。第一轮看:每个参与者是否至少连接了一个用例?每个用例是否至少由一个参与者触发?第二轮看:是不是所有用例都放进了边界框、所有参与者都放到了框外?这两轮自查能拦截掉一半以上的粗心丢分。
4. 软考真题怎么考:从题目套路反推复习重点
软考中级软件设计师的案例分析题,用例图几乎是必考内容,题型通常有两种:一种是给出需求描述,让你补充用例图中的空缺项或指出错误;另一种是直接让你根据描述画出用例图。第一种出现的频率更高,因为阅卷方便,也更容易拉开差距。
4.1 高频考点:用例图补全题
这类题会给出一个半成品的用例图,图里有几个空白的椭圆或方框,让你根据需求文字填写参与者名称、用例名称,或者判断某处关系是否正确。
从历年的真题来看(比如网上流传很广的图书管理系统用例图真题),常见的设问方式包括:
- 请你补充图中A、B、C处的名称,A通常是参与者,B和C通常是用例。
- 请指出图中包含关系和扩展关系各一处,并说明理由。
- 判断某个用例应该属于读者还是管理员,并解释原因。
应对这种题,我的方法是先读系统名称定边界,再找题干中的动词短语对应用例。比如题干里出现“读者可以查询图书信息”,那“查询图书”就是一个用例,参与者是“读者”。题干里出现“如果读者卡过期,系统拒绝借阅”,那么“借阅图书”和“处理过期读者卡”之间必然是扩展关系,而且箭头方向是从“处理过期读者卡”指向“借阅图书”。做题时先标出所有动词短语,再标出条件状语(如果、当、例外时),前者对应包含或普通用例,后者对应扩展关系。
4.2 高频考点:需求描述中的用例提取
还有一种题会给你一大段文字,要求提取所有用例并判断参与者和用例的归属。这种题其实不用背,全靠阅读理解能力,但有两个技巧可以省时间:
第一,找出所有“角色名词”,在文中圈出来,判定是否为参与者。第二,找出所有“能做什么”的句子,把“能”后面的动词短语变成用例名。第三步,将用例归并,同一个名字的工具反复出现,只画一次。最后再检查可能被遗漏的“非功能性需求”(如“系统需要记录日志”)——注意,这类不属于用例,不需要画出来。
这里要特别提醒:不要看到“系统”两个字就认为它是参与者。“系统”本身不是参与者,只有在极少情况下,你的系统需要调用另一个外部系统时,那个外部系统才是参与者。比如图书管理系统调用校园一卡通系统验证身份,此时“校园一卡通系统”作为一个参与者出现在图上。
4.3 答题模板与得分话术
案例分析题除了画图,还常常要求你用文字解释某个设计决定。背一套得分话术很有必要:
- 问“为什么要用包含关系?”答:因为本用例在执行过程中必然包含某个公共功能,去掉它则流程不完整,体现了功能的复用。
- 问“为什么要用扩展关系?”答:因为该功能只在一定条件下才执行,属于基础用例的可选分支,去掉后不影响主流程的完整性,提高了用例的灵活性。
- 问“为什么这个角色不是参与者?”答:该角色不直接与系统交互,没有独立操作目标,仅作为业务背景中的外部角色存在。
这些话术不用一字不差,核心踩分点是“必然包含”还是“可选分支”,再加上“复用”或“灵活性”这两个关键词,基本能得分。
5. 老师不讲的避坑清单:5个常见错误
用例图看着简单,但每届课程设计和期末考试,我都能看到有人踩同样的坑。这里我把最常见的5个错误捋一遍,也欢迎你对号入座。
5.1 错误一:把业务流程步骤画成了用例
把“输入用户名”“点击提交”“验证身份”这种操作步骤当成用例,是新手最容易犯的错误。用例应该是有业务价值的完整功能,“输入用户名”只是“登录系统”的一步,不是一个完整的用例。判断标准是:这个用例描述的结果对参与者有没有独立的价值?如果没有,它就只是用例内部的一句话。
5.2 错误二:包含和扩展方向画反
这个错误在考试中最常见,扣分也最冤。记住我上面的口诀:“包含箭头指向公用,扩展箭头指向基础”。再解释得透彻一点,当你在图上看到<<include>>,箭头指向的那个用例是“每次都要执行的基础准备”,比如“验证身份”;当你看到<<extend>>,箭头指向的那个用例是“主流程”,比如“借阅图书”,而箭尾的用例是“特殊情况才执行的补充流程”,比如“处理借阅超限”。方向反了,语义就完全反了。
5.3 错误三:参与者和用例之间直接画包含/扩展线
包含和扩展是“用例与用例”之间的关系,不是参与者和用例之间的关系。参与者与用例之间只画实线关联。我看到有些同学在图里把参与者用虚线箭头连接一个用例,还写上<<include>>,这在一个专业的评审眼里,是原则性错误。
5.4 错误四:系统边界内部混入参与者
系统边界框内只能放用例,参与者必须在框外。边界框表达的是“系统能做什么”,参与者代表“外部谁在用”,两者混淆会导致图面语义错乱。还有人在边界框内画两个小框,把管理员和读者放在里面,这就等于告诉阅卷老师你没有理解边界的意思。
5.5 错误五:用例图企图表达流程顺序
UML中表达流程顺序的图是活动图或时序图,用例图不负责表达顺序。有人在用例之间画箭头表示先做什么、后做什么,这完全背离了用例图的作用。用例图是静态的功能视图,用例之间只有关系,没有先后顺序。如果觉得用例图无法表达业务过程,应该配合活动图来补充,而不是硬塞到用例图里。
6. 复习建议:三张图、三道题、一遍讲
最后分享一个我复习用例图时的实操方法。我把它叫作“三张图、三道题、一遍讲”,适合在考前一周内执行。
6.1 三张图:精画三个经典系统的用例图
选三个经典系统练手:图书管理系统、网上购物系统、学生选课系统。每个系统的用例图都要完整覆盖所有核心用例,并且强制自己画出至少一个包含关系和一个扩展关系。画完后,对照参考答案查漏补缺,重点看关系方向有没有画反。这三个系统涵盖了绝大多数案例分析题的变体,练熟了之后大部分题目都是熟悉场景。
6.2 三道题:从真题里找感觉
至少做三道历年软考真题的用例图案例题,不要只看,要动笔写和画。真题的答案往往具有示范性,做完后认真比对,特别注意参考答案里的用例命名方式,以及它如何取舍用例粒度。这一遍的收获比看十遍教材都大。
6.3 一遍讲:合上资料给自己讲课
找一个完全没接触过用例图的同学,或者干脆对着镜子,用十分钟把用例图的核心知识点讲一遍。如果中途卡壳,说明这个地方你还没吃透。我只讲了一遍就发现自己对扩展关系的应用场景理解不到位,回头翻教材才发现问题出在“条件触发”这个语义理解上。
复习用例图不用死记硬背,它的逻辑性很强:先圈人,再写事,然后找关系,最后画边界。理清这条思路,不管期末考还是软考,用例图这部分都不会拖你后腿。