☰
UML建模图书管理系统需求分析:四张图落地顺序与避坑指南
2026/10/11 13:59:28 网站建设 项目流程

简介:一份以图书管理系统为案例的UML建模需求分析报告,主要面向正在学习UML建模、面向对象分析与设计的高校学生,以及需要完成课程设计或毕业设计的开发者。报告从借书者、图书管理员、系统管理员三类用户的实际需求出发,依次建立用例模型、静态模型、动态模型与实现模型,覆盖用例图、类图、顺序图、活动图、协作图、构件图和部署图;其中类图明确定义了Item、Title、Loan、Reservation、Borrower等核心类,顺序图则直观呈现了借书、还书等典型业务的交互过程。压缩包内为单个doc文档,容量约265KB,内容结构完整,阅读方便。目前已有2496人学习,适合作为UML实践教学的补充材料,也可为图书管理系统开发提供从需求分析到系统实现的完整参照。

1. UML建模图书管理系统需求分析:从借书流程到四张图的落地顺序

以“UML建模——图书管理系统需求分析报告”为标题的交付物,在课程设计、毕业设计和中小型软件立项评审里几乎每周都出现。它的核心不是画几张好看的图,而是把借书、还书、预约、逾期罚款这些业务规则,用用例图、类图、时序图、状态图表达成无歧义的文档。很多人图画得漂亮,但“一本书和它的物理副本怎么区分”“借阅额度上限写在哪”“借出失败有哪几条分支”这类问题一推就散。这篇文章按一条可复现的顺序展开:需求收集怎么拆、四类图怎么画、约束参数怎么落、评审前要自测哪些点。适合要交课程设计报告的学生、备考软考UML试题的考生,以及正经做图书管理系统需求梳理的开发人员。

2. 需求收集是UML建模的地基:角色、用例与系统边界怎么定

2.1 先拆需求原文,不急着开画

我见过很多UML建模翻车案例,第一幕都是同一个画面:拿到题目后直接打开绘图工具,一边编类名一边想业务。等画到第三张图才发现,自己连“读者借书上限是多少”“能不能预约在馆的书”都没搞清楚。所以这个标题下的第一步,不是任何图形,而是把需求原文拆成“角色、动作、对象、规则”四元组。

比如一段典型需求原文:“读者凭读者证到服务台借书,每张证最多借5本,借期30天,逾期按每本每天0.1元缴纳罚款。”拆解结果是:

角色动作对象规则
读者借书图书/复本每证最多5本,借期30天
图书管理员办理借书读者、图书验证读者证有效性,检查在馆状态
读者、图书管理员归还图书图书逾期按0.1元/本/天计罚

这一份表我建议直接放进需求分析报告的附录,后面画用例图、类图、时序图、状态图时,全部对着这张表核对。这表的价值在于把自然语言里的行为主体找齐了:很多新手的用例图只有“读者”一个角色,漏了“图书管理员”,就是因为没做这步拆解。拆完表后再界定系统边界,图书管理系统需求分析范围内一般不包含图书馆门禁和RFID盘点硬件,除非题目明确要求,否则外部设施不要拉进系统模型里。

2.2 用例图怎么画:用PlantUML脚本走出最小可运行姿势

用例图的落地工作,在一个需求分析报告里至少要包含:参与者、用例、系统边界三要素。我习惯用PlantUML画,理由是纯文本脚本可以进需求库、进Git,评审时改一行就能重新生成图,比在绘图软件里挪矩形高效得多。下面这份就是图书管理系统的用例图最小脚本。

@startuml left to right direction skinparam packageStyle rectangle actor "读者" as reader actor "图书管理员" as librarian actor "系统管理员" as admin rectangle "图书管理系统" { usecase "图书查询" as UC1 usecase "借书" as UC2 usecase "还书" as UC3 usecase "图书维护" as UC4 usecase "读者档案管理" as UC5 usecase "逾期罚款处理" as UC6 usecase "借阅统计报表" as UC7 } reader --> UC1 reader --> UC2 reader --> UC3 librarian --> UC2 librarian --> UC3 librarian --> UC4 librarian --> UC6 admin --> UC5 admin --> UC6 admin --> UC7 @enduml

解释一下脚本里的参数:left to right direction把参与者放在左侧、用例放右侧,生成的图片宽度更适合放进Word报告横排;skinparam packageStyle rectangle让系统边界变成矩形块,评审能一眼看出哪些用例落在系统内部;-->代表参与者与用例之间的关联关系,也就是谁发起这个用例。不同的软件工程教材对用例图的箭头语义定义略有出入,但《UML用户指南》里的定义是最通用的:参与者抬头发起的用例就是主用例。

脚本里我刻意没有使用<<include>>和<<extend>>虚线关系。课程设计或中小型需求报告这两者的优先级不高。加入include和extend会让图显得专业,但问题是对初级评审来说,它们往往是模糊性的来源。比如“还书”不是“借书”的扩展,而是独立用例;“图书查询”也不是“借书”的include,查询作为一个完整目标独立存在。等用例粒度已经稳定时,再回头补include/extend语义。

用例图生成后,光有图还不够,报告需要一张“用例-规则”映射表。比如“借书”这条规则,在需求分析报告正文里应当写成“读者持有效读者证,每证最大借阅量5本,借期30天,逾期按0.1元/天罚款”。这张表是后面类图、时序图、状态图的输入参数,表里每改两个字,后面的图大概率要跟着改。

2.3 用例图评审:三个必看的检查点

第一个检查点:每个用例是否是可被参与者感知的目标。“系统登录”“修改密码”不是用例,它们是达成借书、还书、图书管理这些目标的前置动作。谁感知到这个目标的存在?读者和管理员感知的是“借到书”,不是“登录成功”。

第二个检查点:是否每个用例都有发起者。我审过的一份报告里,有个叫“自动计算罚款”的用例没有连线到任何参与者。这说明需求分析人把内部功能误判成了用例。罚款的产生必须挂在一个真实的参与者动作上,比如“还书”用例的扩展流程里,或者“逾期罚款处理”用例由图书管理员发起。没有发起者的用例,说明系统边界和角色定义出问题了。

第三个检查点:用例总数控制。一个图书管理系统需求分析报告,8到12个主用例是正常区间。打开绘图工具一口气画出20个用例的,基本是把“系统登录”“修改密码”“图书分类维护”“打印借书小票”全当用例了,属于分解没有遵循目标一致性。修整方式只有一个:把用例往上提一层,凡是能合并成更大用户目标的活动都合并,比如“图书分类维护”和“图书信息修改”并入“图书维护”。

3. 类图是需求分析的骨架:图书、读者、借阅记录怎么抽象

3.1 书目与馆藏复本必须分开:类图建模的第一个硬决策

图书管理系统需求分析报告最容易在评审时挂掉的,就是类图里只有一个“图书”类。现实中图书馆借书的粒度根本不是书目,而是物理复本:同一本《活着》可能有5个复本,5个复本的状态可能是在馆、借出、预约保留、修补中各不相同。书目层对应的是ISBN、书名、作者、出版社这些稳定描述;馆藏复本层对应的是条码号、馆藏位置、当前状态。不把这个拆出来,后面借书、预约、盘点、丢失登记全部没有载体。

@startuml class Reader { -readerNo : String -name : String -readerType : Integer -maxBorrowCount : Integer -borrowedCount : Integer +borrow(bookCopy : BookCopy) : Boolean } class Book { -isbn : String -title : String -author : String -publisher : String -publishDate : Date -category : String -price : Double } class BookCopy { -copyId : String -shelfLocation : String -status : Integer +changeStatus(status : Integer) : void } class BorrowRecord { -recordId : Integer -borrowDate : Date -dueDate : Date -returnDate : Date -status : Integer } Reader "1" --> "*" BorrowRecord Book "1" --> "*" BookCopy BookCopy "1" --> "*" BorrowRecord @enduml

这段PlantUML里的连线和类名都是需求阶段才会用到的模型级描述。Reader "1" --> "*" BorrowRecord表示一个读者有多条借阅记录,这条关联决定了数据库里reader_id外键的位置;Book "1" --> "*" BookCopy表示一个书目下有多个在册复本;BookCopy "1" --> "*" BorrowRecord表示一个复本在不同时间点可以有多条借阅历史记录。类中属性的可见性我用的是-私有和+公有,在需求分析报告阶段属性可见性不是必须的,但写上更接近“类设计已可交付”的状态,软考UML试题也喜欢考可见性符号。

Reader类里的maxBorrowCount和borrowedCount,在需求分析阶段建议保留。borrowedCount在逻辑上可以由“BorrowRecord中未归还的记录条数”计算得到,属于派生属性,但写进类图能让评审直观看到借阅额度校验所需的参数。真正落到数据库设计时,再决定是把borrowed_count作为冗余字段实时更新,还是每次借书时用count()统计。

3.2 类图怎么画:关联、聚合、依赖三选一的裁决规则

类图画完实体和属性,接下来的必修课是决定连线类型。最常见的错误是把所有有关系的东西全部用实线画成关联,评审问一句“这两个类的生命周期谁持有谁”就答不上来。我在图书管理系统里采用的裁决口径如下。

聚合关系在“部分”和“整体”有明确的拥有关系,但各自生命周期独立时使用。Book与BookCopy是典型聚合:删除书目意味着复本也不存在,但复本在删除之前可能还有独立的历史借阅记录,所以不建议用更强的组合。组合关系要求部分随整体同生共死,在图书管理系统里几乎没有;如果硬要用,你很难回答“读者证注销后其借阅记录要不要删除”这个问题。依赖关系最宽松,两个类只是方法参数或局部变量层面的使用关系,例如Reader.borrow(bookCopy : BookCopy)这个方法的参数里有BookCopy,这就是依赖,不是关联。

模块级别的形式化判法是:能回答“整体删除后,部分保留还是销毁?”的,用组合或聚合;不能回答的,用普通关联;仅仅是参数引用,用带箭头的虚线依赖。仔细看很多教材和标准答案,它们把Reader到BorrowRecord画成组合,理由是“借阅记录属于读者”。但实际业务中读者注销,借阅历史一般不销毁。在需求分析报告里评这样一处关系是否适用,比把整张图画的规整更重要。

3.3 借阅规则必须挂在类图上:规则要落在明确的位置

很多初学者把“最多借5本”当作Reader类里那个maxBorrowCount = 5的属性值就完了,评审问“去哪儿校验”,回答说“写在业务层”。需求分析报告得把这个“写在业务层”具体化,不然实现人员就得自己发挥。我一般会在类图里补一个服务类,把借书行为集中到它上面,让规则位置可查。

@startuml class BorrowService { +borrow(reader : Reader, bookCopy : BookCopy) : BorrowResult +returnBook(reader : Reader, bookCopy : BookCopy) : ReturnResult } Reader --> BorrowRecord : 1 -> * BookCopy --> BorrowRecord : 1 -> * BorrowService ..> Reader : 校验额度 BorrowService ..> BookCopy : 校验状态 BorrowService ..> BorrowRecord : 创建/更新记录 @enduml

这个图里的BorrowService对应需求分析中的“借书/还书”用例实现者。..>是依赖关系,说明BorrowService只是使用Reader、BookCopy、BorrowRecord,不持有它们的长期引用。规则位置在这里被显式化:借书时执行“校验额度”和“校验状态”,两项都通过再调BorrowRecord创建记录。报告中相应位置单独列一张业务规则表,写规则编号、适用类、约束表达式和实现建议,其中实现建议一栏标注“由BorrowService实现”,这才是把规则落进需求文档的严谨做法。

4. 时序图与状态图:把借书还书流程走通,需求才算闭环

4.1 借书时序图:消息不是画线,是定义接口

时序图要解决的是“借书”用例在对象之间的协作顺序,它比类图更接近代码结构,因为消息名几乎就是将来的方法名。下面这段借书时序图适合直接作为报告素材,它是围绕借书过程中最常见的三个校验点组织的。

@startuml actor "读者" as reader participant "图书管理员" as lib participant "BorrowService" as service participant "Reader" as r participant "BookCopy" as bc participant "BorrowRecord" as record reader -> lib : 出示读者证与图书 lib -> service : 发起借书请求 service -> r : 查询借阅额度 r --> service : 返回已借数量与额度上限 service -> bc : 查询复本状态 bc --> service : 返回状态(available) service -> record : 创建借阅记录 record --> service : 返回记录创建成功 service -> bc : 更新复本状态(status=BORROWED) alt 额度不足 或 状态异常 service --> lib : 返回借书失败原因 else 校验通过 lib --> reader : 借书成功 end @enduml

看一下消息的先后顺序:读者把书和证交给管理员,管理员作为系统前台的操作用户调用BorrowService,服务内部先查额度、后查状态,再创建记录、更新状态。alt片段是借书失败分支的归属位置,把失败条件画在交互片段里,比活动图更精确地贴合类图方法会怎么样。返回值用虚线箭头,实线箭头是请求消息。很多同学这地方犯的错是“查询借阅额度”后又画一条“返回已借数量”的实线,导致消息数量翻倍,评审对照类图方法数时对不上。

评审借书时序图时,我习惯对三个点:消息发起者是不是参与者或系统对象;借书失败分支是否覆盖额度不足和状态不可借;有没有出现跳过BorrowService直接操作数据库的越层消息。但凡这三个点有一个过不去,报告要么被要求返工,要么实现阶段藏一个隐蔽的绕过业务校验的操作入口。

4.2 活动图分支结构:借书流程的规则梳理

时序图画的是协作,活动图画的是控制流。图书管理系统需求分析报告里活动图只画重要的就好,我推荐画两个:借书流程和还书流程。下面这套分支清单是借书流程直接套用的。

  1. 读者提交借书申请。
  2. 校验读者证是否有效:无效则返回错误提示,流程结束;有效则进入下一步。
  3. 校验可借额度:已超过maxBorrowCount则返回额度不足提示;未超过则进入下一步。
  4. 校验复本状态:为“已借出”或“已预约(非当前预约者)”则返回不可借提示;为“在馆”则创建借阅记录、更新复本状态为“已借出”,流程结束。

活动图里真正的价值不是这张图展示的这四行,而是每个判断分支跟需求原文能对上。拿第四步的状态判断来说,如果需求里有预约规则“归还后的图书为预约者保留3天”,那么借书活动图里就应该有“该复本处于预留状态且预留给当前读者”通过、“预留状态但预留者不是当前读者”拒绝的细分判断。这些细节不做,时序图和活动图都是空壳。

图书管理系统这类流程,业务上不存在真正的并行任务,所以不需要活动图的并发分叉叉符号。如果看到报告的活动图里出现两条并行泳道同时操作同一本书,多半是建模人把进度条动画或者异步通知也画进了业务流程。这类编辑器生成的豪华图,评审阶段反而是扣分项。

4.3 状态图:一本书的状态决定了你能否借到它

类图画了BookCopy.status属性,但这个属性到底有哪些合法取值、取值的转换由哪些事件驱动,必须靠状态图表达清楚。以下状态图是图书管理系统需求分析里可以直接复用的版本。

@startuml [*] --> 在馆 在馆 --> 已借出 : 借出成功 在馆 --> 已预约 : 读者预约 已预约 --> 已借出 : 预约者借出 已预约 --> 在馆 : 预约超时未取 已借出 --> 在馆 : 正常归还 已借出 --> 损坏 : 归还时发现损坏 已借出 --> 丢失 : 借出期间挂失 损坏 --> 在馆 : 修复后重新置架 丢失 --> [*] : 注销复本 @enduml

状态框里的名字是结果状态,箭头标签上写的是触发事件。这里最容易绕晕人的是“已借出”:它是状态,不是一个流程步骤。借出事件触发状态从“在馆”到“已借出”,归还事件触发从“已借出”到“在馆”。如果想要在报告里体现“借出动作依次经过哪些判断”,那是活动图的职责,不是状态图的职责。

状态图里的每个转移事件,都得在需求原文或规则表里找到出处。比如“预约超时未取”这个转移,需求里必须有“图书归还后为预约者保留3天,超过3天未取则回到在馆状态”这样的描述。如果原文没有,说明该需求尚未明确,正常做法是回给评审或需求方确认,而不是自己编一个按时段回转的假设。最后把状态值的集合与数据库的status字段取值对照一下,两者必须一一对应,这是需求分析能顺利交接到数据库设计的前提。

5. 需求分析建模避坑清单:5个让报告返工的真实问题

5.1 类和状态建模上的三个经典选择坑

现象1:类图只有一个“图书”类,ISBN、书名、条码号、当前状态全部挂在一个类里。评审问“同一本书有5个复本,其中2个被借走、3个在馆,怎么表示”,报告没有答案。 原因1:需求分析阶段没有做领域词汇梳理,把日常口语的“书”等同于系统里的抽象实体。 解决1:建立词汇表,区分“书目”和“复本”两层概念,类图拆出Book与BookCopy,数据库相应模型也拆成book与book_copy表。切记借阅发生时操作的对象永远是BookCopy,而不是Book。

现象2:状态图里把动作当状态,画成“待借出→借出中→待归还→已归还”的流水线。 原因2:混淆了“状态”和“事件”。状态回答“这本书当前处于什么在场状态”,事件回答“是什么动作导致状态变化”。借出是导致“已借出”状态的事件,借出中的过程不算状态。 解决2:每个状态框只放状态名词,事件写在转移箭头标签上。状态图的状态值集合必须与数据库BookCopy.status字段的取值完全一致。

现象3:借阅规则只写了“读者最多借5本”,类图上没有任何位置承载这条规则,时序图里也找不到校验动作。 原因3:规则建模缺位。需求分析阶段图已经画完,但规则还留在自然语言里,实现人员只能自己猜放哪。最常见的是把maxBorrowCount定成一个代码里的常量,或者每次写死在一个方法里,后续改额度要改代码。 解决3:在类图中增设BorrowService服务类,把额度校验和状态校验作为服务方法的前置条件。报告附一张业务规则表,每条规则编号、适用类、约束表达式、实现建议四列,逐条对齐。

5.2 图间一致性上的两个雷区

现象4:借书时序图里,“查询借阅额度”之后又画了一条“返回已借数量”的实线箭头,整张图消息数是方法数的两倍。评审追问这条消息由谁处理、要不要写接口,报告方支支吾吾。 原因4:把“方法调用返回结果”和“发起下一次调用”混为一谈。返回是同步调用的一部分,不应变成一个新的独立消息。 解决4:时序图中请求消息用实线箭头,返回值用虚线箭头,仅仅画在请求消息下方一行,不额外占用独立消息编号。评审时数一下请求消息条数与类图方法数,两者差距太远就说明图需要收敛。

现象5:用例图里画了“系统登录”“修改密码”“图书封面图片管理”等高密度功能,用例总数超过20个。核心的借书流程反而被淹没。 原因5:没有按用户可感知目标划分用例,把实现层面的功能按钮全部平铺。 解决5:先保留借书、还书、预约、图书查询、图书维护、读者档案管理、逾期罚款处理、借阅统计报表 8 个主用例,其余一律省略。登录和修改密码作为底层支持放附录,不作为系统模型的一部分突出展示。用例总数回到10个左右后,再回头审视用例之间的include和extend关系。

6. 把UML图沉淀成需求分析报告正文:一个能直接评审的模板

6.1 从四张图到文档的组装

图画完且自检通过后,下一件事是组装成一份可评审的需求分析报告。我固定使用的目录结构如下:引言与范围、领域术语表、参与者与用例总览、用例说明(按每个用例前置条件/主流程/分支流程/异常流程四段展开)、类图与类描述表、借书还书时序图与活动图、书目与复本状态图、业务规则表、非功能性需求。其中领域术语表这一段最容易被漏掉,但也是答辩时评审抓概念歧义的起点。

写用例说明时,建议每个用例一条小标题,前置条件、主流程、分支流程、异常流程各写一小段。比如“预约图书”的主流程是“读者检索到已借出的复本→发起预约→系统记录预约关系并生成预约号→图书归还后系统将复本状态置为已预约”;异常流程就写“预约者3天未取→复本自动回到在馆状态,预约关系关闭”。这些内容会原封不动变成时序图和状态图的转移事件来源。

类描述表我按四列来:类名、职责说明、关键属性及类型、关联说明。拿BookCopy来举,职责说明写“馆藏物理复本,一本书目下可有多个副本”,关键属性写copyId:String、status:Integer,关联说明写“与Book构成聚合,与BorrowRecord构成一对多”。表里所有类的集合和类图严格一致,不允许报告正文提了某个类但类图里没有。

6.2 验证报告没有漏、没有错的三个手段

第一个手段是状态集对表:把BookCopy.status可能存进数据库的所有值列出来,和状态图的状态框逐一对上;多出一个值说明需求没建模清楚,少一个值说明数据库设计会落空。第二个手段是消息条数对图:借书时序图的每个请求消息来说,在类图都能找到对应的方法名,允许方法名稍有出入但不允许存在类和时序图联不上的方法。第三个手段是规则对档:业务规则表的每条规则至少被用例图、时序图或状态图中的一处引用,规则落不了地的位置就是下次评审的提问点。

最后说一个我改过的习惯:以前我先画类图后补用例图,结果借还书用例和类图字段经常对不上,来回返工。现在固定顺序是需求名词拆解→用例图→类图→时序图→活动图→状态图→规则表。发现问题时先改规则表和词汇表,再联动更新图。如果你只带一张图离开这场需求分析,那应该用例图,因为参与者、边界、核心流程全部在它之上最清晰。希望这些踩坑经验能帮你少走几轮返工。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询