简介:吉林大学软件系统分析与设计(SSAD)课程设计满分报告,以体育竞赛注册系统为项目背景,完整展示了基于UML的面向对象系统分析与设计全过程。报告从设计目标与原则、需求捕获入手,逐步展开省联盟注册、比赛组登记、取消与退款、信息查询等核心用例,并绘制了用例图、类图、顺序图,进而完成数据库持久化设计和部署图及界面设计,形成可追溯的完整建模链条。同时特别结合中国情境,将信用卡公司与银行整合为统一的银行支付平台来处理支付与退款接口,能帮助软件工程相关专业学生理解如何将理论方法落到实际项目中。资源包内仅含1个docx文档,大小约1.39MB,章节结构清晰,可作为课程设计报告写作模板与设计流程参考。目前已有902人学习浏览,适合正在完成SSAD、软件建模或系统分析设计类作业的高校学生借鉴。
1. 从拿到题目到交报告,最容易被低估的是需求分析这一关
某高校软件学院系统分析与设计(SSAD)课程设计里,最常见的题目就是做一个体育竞赛注册系统:省联盟登记信息、报名比赛组、缴费退款,竞赛组织者做全局查询和打印。第一次接触这种题,很容易觉得“不就是把界面画出来、把增删改查写出来嘛”,真正动手才发现,评审老师最在意的是你如何从需求走到设计、再落到数据库和接口,每一步都有据可查。
这套方案采用面向对象的设计策略,用 UML 完成全部系统分析与设计,包含需求分析、用例图、用例规约、类图、顺序图、数据库设计和银行支付平台接口设计。无论你是做课程设计还是准备毕业设计的文档部分,这套完整的设计思路都能直接拿来当底稿,照着往下走就不会出现“图画完了但要问什么说不清楚”的尴尬。先看需求边界在哪里,再从需求推用例、推类图、推表结构,最后落到验收。
2. 需求分析与流程梳理:三种角色、四类用例、一条退款规则
2.1 角色权限矩阵:不同登录者能看到什么
这个系统的角色一共有三类,权限完全不同,很多同学在这里画用例图时就开始乱挂关系。省联盟管理者负责注册联盟信息、登记比赛组、缴费、取消比赛组、查询并打印本联盟登记记录;全国竞赛组织者可以查询并打印全部联盟和比赛组信息;裁判是最容易被漏掉的角色,需求里明确提到裁判只查看自己主持的比赛组信息。
角色权限可以整理成一张矩阵表,这也是评审老师最爱看的第一张表:
| 功能 | 省联盟管理者 | 竞赛组织者 | 裁判 |
|---|---|---|---|
| 注册联盟信息 | 操作 | 只读 | 不可见 |
| 登记比赛组 | 操作 | 只读 | 不可见 |
| 取消比赛组并退款 | 操作 | 只读 | 不可见 |
| 查询本联盟登记记录 | 操作并可打印 | 只读 | 不可见 |
| 全局信息查询打印 | 不可见 | 操作 | 不可见 |
| 查看分配的比赛组 | 不可见 | 只读 | 操作 |
有这张表,后面画用例图时参与者边界就不会模糊。裁判不能看到缴费金额,组织者不需要登记联盟信息,这些都是权限设计的一部分。另外要注意,需求里提到查询用例时“竞赛组织者 ID 可以显示所有信息”,所以组织者虽然不参与注册操作,但他拥有最高查询权限。
2.2 四条主业务流:从注册到打印的完整链路
系统的核心业务流程有四条,对应四个主用例。注册联盟信息这条链路最长:省联盟管理者进入系统、选择注册联盟、系统先判断当前时间是否允许注册、输入联盟名称和地址、登记比赛组、跳转支付平台缴费、系统更新记录并分配联盟 ID,最后页面显示注册成功。这里有一个容易被忽略的设计点:注册联盟和登记比赛组是连在一起的,意味着联盟信息和比赛组信息要在同一个事务里完成创建,双方之间有强关联。
登记比赛组强调的是“先匹配后缴费”:省联盟管理者登录后,系统按类别和级别匹配出可选的比赛组,管理者确认后跳转到支付平台,支付平台反馈成功,系统分配裁判,最后登记成功。顺序图里的三个关键节点是系统匹配比赛组、支付平台回调、裁判分配,这三个节点也是数据库里外键关系最多的地方。
取消比赛组这条流程最有意思,系统在取消操作发生时就要根据时间计算出退款金额,跳转支付平台退款,再更新记录。查询联盟信息这条链路相对简单,登录后按 ID 展示信息,但有一个拓展示例要预留:组织者可以打印所有信息,联盟管理者可以打印本联盟信息,裁判可以看到自己主持的比赛组,这三种查询的数据范围由登入 ID 的角色决定。
2.3 最容易被误读的退款规则:时间分支和整体半退
退款规则是整个需求里含金量最高的一段,也是答辩时最容易翻车的地方。原题给出了很明确的约束:比赛开始之前的一个月以上取消比赛组,返还全部注册费;赛前一个月内取消,返还一半费用;比赛开始后不再退款;而联盟如果取消整个登记,只能收到原注册费的一半。注意这里两套策略是并存的,一个是“比赛组级取消按时间退”,另一个是“联盟级整体取消固定一半”。
很多同学会把这两套混成一锅粥,画用例规约的时候要么丢了时间分支,要么把联盟整体取消混进比赛组取消。标准做法是把这两条策略拆成独立业务规则,并且在数据库的退款记录里单独存一个 refund_type 字段,用来区分是比赛组级退款还是联盟整体退款。退款金额的计算逻辑可以写出一个明确的函数:
double calcRefund(int daysBeforeStart, boolean isLeagueCancel, double fee) { if (isLeagueCancel) { return fee * 0.5; // 联盟整单取消,固定半退 } if (daysBeforeStart > 30) { return fee; // 赛前一个月之前,全退 } if (daysBeforeStart > 0) { return fee * 0.5; // 赛前一个月内,半退 } return 0; // 比赛开始后,不退 }这个函数里 daysBeforeStart 是距离比赛开始的自然日数,isLeagueCancel 用来区分取消的粒度。把这个逻辑前置到需求分析阶段讲清楚,后面所有设计都会围绕它展开,而不是等到数据库设计时才发现缺字段。
2.4 业务规则清单:把需求转成可校验条目
需求分析最后一个动作是整理业务规则清单,让每条需求都变成可以验证的条目。比如 R1:联盟名称全局唯一,一个联盟只能注册一次;R2:注册窗口以系统日期为准,系统关闭时间不允许注册;R3:比赛组必须先匹配类别和级别,再进入缴费流程;R4:支付必须走支付平台,内部系统不直接处理资金;R5:赛前三十天以上取消全退,三十天内取消半退,开赛后不退;R6:联盟整体取消按原费用半退且开赛后不可取消;R7:比赛组登记成功后必须分配裁判;R8:组织者可查询并打印全部信息,联盟管理者只能查询并打印本联盟信息。
有了这份清单,后面画用例图时备选事件就会写得很整齐,数据库设计时也知道哪些字段必须有。交付时把规则清单附在文档前面,评审老师可以快速判断你理解了需求,而不是只会画方框和箭头。
3. 用例图与用例规约:会画图不算完,能写清备选流才算真懂
3.1 用例图怎么布局:参与者边界和系统边界
用例图的核心不是美观,而是划分边界。系统边界框住内部用例,参与者放在边界外。体育竞赛注册系统有三个参与者,省联盟管理者、竞赛组织者、裁判,和一个外部系统:银行支付平台。四大用例是注册联盟信息、登记比赛组、取消比赛组、查询联盟信息。查询联盟信息的参与者是三个人共用的,这是最典型的需要连三条关系的用例。
布局时要注意三层结构:最外层是参与者,中间层是主用例,最里层是扩展用例。支付平台虽然不在参与者列表里,但它承担了缴费和退款两个交互,必须作为一个外部参与者画在边界的另一侧,否则支付时序图就没有头。用例图的价值是让读者一眼看到“谁用系统、系统做什么、外部依赖什么”,所以尽量不要在用例图里画太多子流程,具体分支放到用例规约去写。
3.2 用例规约模板:基本流、备选流、前置条件
用例图画完之后,每一步交互都要落到用例规约里,这是在课程设计报告里拉开分数差距的关键。以“注册联盟信息”为例,完整的规约应该包含用例名称、参与者、前置条件、后置条件、基本流、备选流与业务规则,下面是一个可以直接照抄的模板:
| 项目 | 内容 |
|---|---|
| 用例名称 | 注册联盟信息 |
| 参与者 | 省联盟管理者 |
| 前置条件 | 系统处于注册开放期;该联盟未被注册 |
| 后置条件 | 生成联盟 ID,登记记录初始化,支付成功 |
| 基本流 | 1. 管理者进入注册系统;2. 选择注册联盟;3. 系统判断注册时间;4. 输入联盟名称、地址;5. 登记比赛组;6. 缴纳注册费;7. 系统更新记录;8. 分配联盟 ID;9. 显示注册成功 |
| 备选流 | 3a 系统关闭不可注册;4a 联盟已注册不可重复;6a 缴费失败,注册流程终止 |
这种规约表格的价值在于它把“系统根据时间判断是否可以注册”“已注册联盟不可重复注册”这些需求细节全部固化下来。写规约时最容易犯的毛病是只写基本流,把备选流当成“补充说明”随手丢几个,实际上备选流才是评审老师判断你有没有把需求读透的证据。备选流不齐,实现阶段一定会出遗漏分支。
3.3 把备选流写细:登记比赛组的三个分支
登记比赛组的用例规约里,备选流最值得打磨。基本事件是登录、查看比赛组、选择缴费、跳转第三方平台、支付成功反馈、分配裁判、显示登记成功。备选事件有三类:系统关闭不可登记;支付时未完成支付,反馈失败后跳转回缴费步骤;系统显示登记失败后跳转回重新核对比赛组。
这三条分支对应到代码实现里就是三个异常出口。特别是支付失败那条链路,真实环境里会遇到“支付平台已经扣款但系统没收到回调”“银行返回超时但用户已输入密码”等边界情况,所以在规约阶段就要把“反馈支付失败”描述为“系统收到支付失败或超时信号后,回到缴费界面且不改变登记状态”,这样实现阶段不会出现支付状态被写脏的情况。
3.4 从用例规约到测试用例的映射
用例规约写好的直接收益,是验收阶段可以逆向生成测试用例。比如“注册联盟信息”这个用例,可以映射出三条测试用例:正常路径下完整注册并生成联盟 ID;系统关闭状态下进入注册流程被拦截;联盟名称已存在时注册被拒绝。“取消比赛组”可以映射出赛前三十天取消、赛前十五天取消、开赛后取消和联盟整单取消四条用例。
把每条备选流编号和测试用例编号一一对上,交付时这个对应关系本身就是验收文档的一部分。大多数课程设计要求画用例图,但不会强制要求写用例规约,写了就是加分项。而且这份规约在答辩时可以直接回答“系统怎么处理异常情况”这类追问,比临场现想答案要从容得多。
4. 类图设计与数据库落地:八个类如何收敛成四张表
4.1 类图职责划分:实体对象、记录对象与外部接口对象
这个系统的类图一共涉及八个类,核心是省联盟、登记记录、比赛组、比赛类别、裁判、银行支付平台,外加登录会话和打印服务两个支撑类。省联盟类持有联盟名称、联盟 ID、联盟地址、会员名称等属性,因为它具有打印登记记录的功能,所以和登记记录类相关;登记记录是信息枢纽,包含比赛组、裁判和费用信息,同时也要能提供查询;比赛组属于比赛类别,类别决定了登记时可选的级别范围。
设计类图时最重要的是想清楚“谁持有谁”的关系。省联盟和登记记录是一对多聚合,一个联盟可以有多条登记记录;登记记录和比赛组是一对一关联,每条登记记录对应一个已报名的比赛组;登记记录和裁判是关联关系,记录里带裁判 ID,表示该比赛组已经完成裁判分配。银行支付平台在这个场景里是第三方工具类,它不持有业务状态,只提供交易接口,所以类图上它和登记记录之间是依赖关系而不是聚合关系。
4.2 类之间关系怎么画:聚合、关联和依赖的区别
评审老师在类图上主要看两类东西:关系箭头的语义和多重性的标注。省联盟“聚合”登记记录,意味着删除联盟时登记记录会被撤销;登记记录“关联”比赛组,说明两者生命周期独立但需要互相引用;登记记录“依赖”银行支付平台,表示业务操作调用外部接口。这三层的耦合程度是递减的,聚合体现归属、关联体现引用、依赖体现调用,不能混着画。
属性标注也要精练。省联盟类不要写太多无意义的修饰字段,把和需求直接相关的信息列出即可:联盟名称、联盟地址、联盟编号、会员名称、创建时间。比赛类别类单独成类而不是做成比赛组的字符串属性,是因为原题明确提到“选择类别和级别”,如果类别和级别是强枚举,后续扩展新项目时会频繁改代码,单独成类更符合开闭原则。
4.3 数据库表结构:主键、外键与三个关键约束
类图落到数据库,核心表有四张:联盟表、比赛组表、裁判表、登记记录表。联盟表的主键是系统生成的联盟 ID,联盟名称作为业务唯一键单独加唯一索引。比赛组表存类别和级别,级别用枚举值,同时保存状态字段区分“待支付”“已登记”“已取消”。裁判表单独保存裁判基本信息和所在组织。登记记录表是业务中心表,持有联盟 ID、比赛组 ID、裁判 ID、费用、支付状态、退款状态和退款类型字段。
表结构字段设计时有两个容易出问题的点。第一个是金额字段用整数还是浮点数,实践中统一用整数存分,避免浮点计算误差;第二个是支付状态和退款状态必须分字段存放,不能挤在一个状态字段里,否则“已支付且已全额退款”和“已支付且已半额退款”无法区分。下面是最核心的两张表的建表参考:
CREATE TABLE league ( league_id INT PRIMARY KEY AUTO_INCREMENT, league_name VARCHAR(100) NOT NULL UNIQUE, address VARCHAR(255), contact_name VARCHAR(50), registered_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE registration_record ( record_id INT PRIMARY KEY AUTO_INCREMENT, league_id INT NOT NULL, group_id INT NOT NULL, judge_id INT, fee INT NOT NULL, payment_status TINYINT NOT NULL DEFAULT 0, refund_status TINYINT NOT NULL DEFAULT 0, refund_type TINYINT, created_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (league_id) REFERENCES league(league_id), FOREIGN KEY (group_id) REFERENCES competition_group(group_id), FOREIGN KEY (judge_id) REFERENCES judge(judge_id) );这两张表分别对应类图中的省联盟类和登记记录类。payment_status 用 0 表示未支付、1 表示已支付、2 表示支付失败,refund_status 用 0 表示无退款、1 表示全额退款、2 表示半额退款,refund_type 区分比赛组级退款和联盟整体退款。多表查询时,典型查询是“按省联盟名称查登记记录”,实际执行的是联盟表和登记记录表的关联查询;竞赛组织者查全部信息就是这个查询去掉联盟过滤条件。
4.4 银行支付平台接口设计与部署边界
原题特别说明了一个环境差异:国内信用卡公司和银行是一体的,所以省联盟、信用卡公司和银行三者之间的交互被简化成系统与“银行支付平台”一个外部系统的交互。这个决策直接影响类图和部署图。部署结构由四块组成:浏览器端界面、应用服务器、数据库服务器、银行支付平台,其中支付平台在系统边界之外,通过 HTTPS 接口通信。
支付平台需要设计三类接口:支付请求、退款请求、支付结果查询。内部系统不直接操作资金,所有资金变动都在平台侧完成,系统只保存平台返回的交易单号和状态。这个“外部平台负责资金安全、业务系统负责状态记录”的边界划分,要在顺序图中表现清楚。注册联盟信息的顺序图里有六个关键步骤:打开注册页面、提交联盟信息、提交支付请求、平台返回支付结果、系统分配联盟 ID、系统刷新页面,每一步对应一个类方法或平台接口调用。
5. 常见问题排查:设计这类系统最容易翻车的五个点
5.1 现象:退款规则前后矛盾,答辩被追问就卡住
一份设计报告里,需求文字写的退款规则是“赛前一个月以上全退、一个月内半退、开赛不退”,用例图的备选事件里却写成了“返还全部金额、返还一般金额、不返还”,这里出现了两个问题:一是“返还是半额”还是“全额”没有写清楚,二是漏掉了联盟整单取消固定半退这条例外规则。
原因就是需求分析阶段没有把退款规则抽象成独立业务规则,而是分散在文字描述各处,没有做一致性检查。解决的办法是在文档开头放一份业务规则清单,把“比赛组取消按时间退”和“联盟整体取消按半退”拆成两条,再在数据库的登记记录表里增加退款类型字段区分两种取消粒度。退款金额的计算逻辑用函数显式表达,开发时照着函数写,报告和代码就不会打架。
5.2 现象:把支付当成瞬时操作,忽略平台回调
很多设计文档里的缴费流程就是“跳转支付平台,支付成功,返回系统”,看起来顺理成章,实际上隐藏着一个定时炸弹:支付平台返回结果和系统收到回调结果之间存在时间差,如果用户支付成功但页面没有跳转,或者平台回调延迟,系统怎么处理?
常见的设计思路是把支付状态设计成有限状态机:待支付、支付中、已支付、支付失败、已退款。支付平台的回调不是“返回一条成功消息”这么简单,系统必须用交易单号去平台查询最终状态,再做状态流转。顺序图里至少要画两个分支:支付平台主动回调成功分支和系统定时查询兜底分支。这个细节写进设计文档,比画十个界面图都更能体现系统设计能力。
5.3 现象:拿业务名称当主键,数据关系剪不断理还乱
原题在持久化设计里写的是“省联盟拥有唯一主键省联盟名称”,如果照着字面实现,把联盟名称作为主键,后续一旦联盟改名,所有登记记录里的外键都要级联更新,伤害面很大。
更稳的做法是用代理主键。联盟表主键用自增 league_id,联盟名称只加唯一索引保证业务上不重复;登记表同样用自增主键 record_id,league_id 做外键。从类图到表结构推导的时候,理论上允许“用业务唯一键做自然主键”,但实际系统里操作成本太高,建议在报告里明确说明采用代理主键的原因。这部分写出分析和取舍,会让整体设计显得更成熟。
5.4 现象:类图画成了数据库表结构,没有设计含量
类图和表结构对照着画是常见错误,最典型的就是类只有属性没有方法,一个类就是一张表的字段列表。类图要表达的是行为职责,省联盟类应该有“查询登记记录”“打印登记记录”的方法,登记记录类应该有“计算退款金额”的方法,裁判类应该有“获取分配的比赛组”的方法。
粘连关系和依赖关系也要比数据库表结构画得更抽象。比赛组类和比赛类别类是“聚合”关系,登记记录和支付平台是“依赖”关系,这些在表结构里无法表达。类图画得不粗不细的标准是:去掉类名看方法和关系,评审老师能猜出这个类负责什么业务。类图没有方法,本质上就退化成了一张实体关系图的替代品。
5.5 现象:用例规约只写基本流,备选流一笔带过
一份满分的用例规约,备选流应该占据一半以上的篇幅。很多人写“取消比赛组”时只写了“系统根据时间判断返还金额”一句,完全没有列出时间分支,导致后续设计退款逻辑时没有任何依据。
备选流是最能体现需求理解深度的部分。取消比赛组至少要写四条备选:赛前一个月以上取消全退、赛前一个月内取消半退、比赛开始后取消不退、联盟整单取消按原费半退。每条备选流还要给出对应的系统响应,例如“赛内开始后取消不退,系统提示不可取消并且不跳转支付平台”。写完备选流之后自测一遍,把每条备选流翻译成一个测试用例,如果发现还有测试场景规约覆盖不到,说明备选流还没写完整。
6. 验收与答辩:用一条主流程回答掉大部分追问
课程设计的验收阶段,建议准备一条完整的演示主流程,把最大的一头风险提前拆掉:注册联盟、登记比赛组、取消比赛组、查询打印。这条流程不是随机演示,而是有顺序讲究的。首先注册一个联盟,引出联盟 ID 生成机制;然后登记比赛组,引出类别级别匹配和裁判分配;再取消比赛组,引出退款规则和支付平台交互;最后查询打印,引出角色权限边界。一条流程走完,需求分析、类图、数据库、顺序图、界面五部分内容就全部串起来了。
答辩时被问到的内容会很集中,评委最常问的三类是:数据库表怎么关联、退款规则边界怎么处理、角色权限怎么控制。数据库关联是顺着登记记录表出发的,解释清楚“登记记录与联盟一对多、与比赛组一对一的关联”即可;退款规则用赛前三十天那条计算函数回答,同时说明退款类型如何区分;权限控制直接引用操作权限矩阵,说明联盟、组织者、裁判在查询范围上的隔离。
以下是一份自查清单,交稿前一项项勾,能避免大半低分情况:是否画出系统边界框并识别出外部支付平台参与者;是否每个用例包含基本流和不少于两条备选流;退款规则时间分支是否和函数实现一致;类图中每个类是否有明确行为和关系标注;数据库主键是否使用代理键且外键指向明确;支付流程是否画了回调与超时分支;是否画出部署节点及外部平台边界;是否准备了完整演示主流程。这套清单用起来很硬核,从那以后我每次交付设计文档前都会强制走一遍,确认每个环节没有“黑匣子”才发给导师。希望帮到你。
本文还有配套的精品资源,点击获取