简介:本资源是一份面向软件工程初学者与课程设计实践者的《图书管理系统》完整开发文档,聚焦需求分析、系统设计与实现全过程,适用于高校软件工程课程设计、毕业设计参考及小型信息管理系统学习。文档以Word格式(.doc)单文件封装,大小535KB,内容涵盖系统目标与三类角色(管理员/读者/系统管理员)功能需求、三层架构设计(Presentation/Application/Data Layer)、SQL Server 2000数据库E-R图与表结构、VB6.0界面与编码实现细节,并附有详细用例图、时序图、类图及模块化开发步骤说明。目前已有441人学习下载,读者可直接获取规范的软件工程文档模板、可落地的数据库设计方案、VB6.0+Rational ROSE协同开发实践路径,以及从需求建模到系统测试的全流程技术要点梳理。
1. 图书管理系统:为什么一个“过时”的VB6+SQL2000组合,反而成了软件工程课设最稳的落地选择?
你可能刚在毕设选题表里看到“图书管理系统”就皱眉——太老、太常见、老师一眼看穿是抄的。但去年带某高校软件工程课程设计时,A同学用VB6+SQL2000交出的完整方案,不仅拿了优秀,还被导师直接推荐给下届当模板。原因很实在:它不拼技术新潮,而死磕软件工程全流程的闭环交付能力——从UML建模(ROSE画出7张规范用例图/时序图/类图)、E-R图到8张表的字段级定义(含主外键约束、空值逻辑、默认值语义),再到ADO连接封装、窗体级事务控制(借书=扣库存+写borrow表+更新reader已借数,三步必须原子),最后连罚款计算规则(超期天数×日罚金)都落在数据库触发器里。这不是写个CRUD Demo,而是用一套被工业界淘汰、却在教学场景中“零抽象损耗”的技术栈,把需求分析→设计→实现→验证这条链路,一环不落地钉进代码和文档。适合谁?需要交完整软件工程文档包(含需求规格说明书、数据库设计说明书、详细设计说明书、测试用例表)的本科生;也适合想快速复现“教科书级MIS系统”结构、避开Spring Boot自动配置黑匣子的初学者。它解决的不是“多酷”,而是“多全、多准、多可答辩”。
2. 需求建模与系统架构设计:三层结构如何用UML图精准锚定三类角色的权责边界
2.1 用例图不是摆设:三类参与者的行为契约必须落到字段级约束
在某高校课程设计评审中,近40%的失败方案栽在“用例图泛化”——画个椭圆写“借书”,却不定义“借书成功需满足:读者状态=有效 ∧ 图书库存>0 ∧ 当前已借数<5”。本方案严格按角色拆解契约:
- 读者:用例仅限查询(bookname/author/kindname多字段模糊匹配)、借阅(校验user_state='有效'且borrow表无未还记录)、续借(仅允许已借30天内且未超期)、还书(触发库存+1、borrow表receivedate写入、punishment表自动计算)。
- 图书管理员:用例锁定为“处理借书”“处理还书”两个操作,禁止直接修改borrow表——必须通过调用
librarian.ProcessBorrow(user_cardno, bannercode)方法,该方法内部执行库存检查、状态更新、日志写入三步。 - 系统管理员:用例明确区分“增删改”权限,如
admin.DeleteBook(bannercode)必须先校验该书无未还记录(关联borrow表count=0),否则抛出ERR_BOOK_IN_USE异常。
提示:所有用例图中的关系线(< > / < >)必须对应到后续时序图。例如“读者续借”< >“读者借阅”,意味着续借流程复用借阅的库存校验逻辑,但增加renew='Y'字段写入。
2.2 时序图驱动开发:以“管理员添加图书”为例的七步原子操作
时序图不是画给老师看的装饰,而是编码前的执行脚本。本方案中“系统管理员添加图书”时序图强制规定以下7步不可省略:
admin对象发送addBook(bookname, bannercode, kindname, author...)请求;system对象调用checkDuplicate(bannercode)——查book表bannercode是否已存在;- 若存在,返回
ERR_DUPLICATE_CODE并终止; - 若不存在,
system调用insertBook(...)向book表插入新行; - 同时
system向log表写入操作日志(admin_name, action='ADD_BOOK', bannercode, timestamp); system触发updateStatistics()更新图书总数统计缓存;- 最终返回
SUCCESS及新生成的book_id。
这个时序图直接决定了VB6代码结构:frmAdminAddBook.cmdAdd_Click()事件中,必须按此顺序调用clsBookManager.CheckDuplicate()→clsBookManager.Insert()→clsLogManager.WriteLog()→clsCacheManager.UpdateTotal(),任何一步失败必须回滚前序操作(ADO中用BeginTrans/CommitTrans/RollbackTrans控制)。
2.3 类图即代码骨架:6个核心类的属性与方法如何映射到VB6模块
类图不是UML练习,而是VB6工程的物理划分依据。本方案6个类严格对应6个.cls文件,且属性/方法名与数据库字段1:1对齐:
clsReader类:属性Public user_cardnumber As String(对应user表主键)、Public user_state As String(值域限定为'有效'/'挂失'/'注销');方法Public Function BorrowBook(bannercode As String) As Boolean内部调用clsBorrowManager.AddRecord(user_cardnumber, bannercode)。clsBook类:属性Public bannercode As String(唯一索引)、Public state As String(值域'在馆'/'借出'/'遗失'/'报废');方法Public Sub UpdateStock(newCount As Integer)强制校验newCount >= 0,否则Err.Raise 500, "clsBook", "库存不能为负"。- 关系映射:
clsReader与clsBorrow为1对多(读者可借多本书),在clsBorrow中声明Public readerRef As clsReader;clsBook与clsBorrow为1对多,在clsBorrow中声明Public bookRef As clsBook。
注意:所有类的方法参数类型必须与数据库字段类型一致。例如
clsBorrow的borrowdate As Date对应SQL Server的Date类型,严禁用String传日期字符串——VB6中用CDate("2023-01-01")转换后传入。
2.4 总体架构设计:三层结构在VB6中的物理实现与数据流控制
本方案采用经典三层架构,但在VB6中需规避“过度分层”导致的性能损耗:
- Presentation Layer(表现层):由
frmLogin、frmMain、frmReaderQuery等窗体构成,只做UI渲染和事件转发。例如frmReaderQuery.txtSearch_Change()不查数据库,只调用clsSearchEngine.SearchByAuthor(txtSearch.Text)。 - Application Layer(业务层):由
clsSearchEngine、clsBorrowManager、clsPunishmentCalculator等类构成,封装全部业务规则。关键设计:clsPunishmentCalculator.Calculate(user_cardnumber)方法中,先查borrow表获取borrowdate和receivedate,再查book表获取pricenumber,最后按DATEDIFF(day, borrowdate, GETDATE()) > 30计算超期天数,所有SQL语句在此层拼接,表现层不可见SQL。 - Data Layer(数据层):由
clsConnection(ADO连接管理)和clsDataAccess(通用CRUD)构成。clsDataAccess.ExecuteSQL(sql As String)方法中,强制要求sql参数必须是预编译字符串(如"UPDATE book SET state='借出' WHERE bannercode=?"),参数值通过cmd.Parameters.Append cmd.CreateParameter(...)传入,杜绝SQL注入。
数据流严格单向:表现层 → 业务层 → 数据层 → 数据库,禁止跨层调用(如frmLogin直接调用clsConnection.Open)。
3. 数据库设计与实现:8张表的字段级定义、E-R关系与ADO连接防坑指南
3.1 E-R图到物理表:三类实体与四类关系的精确落地
本方案E-R图包含3个实体(Reader、Book、Administrator)和4种关系(读者-借阅-图书、管理员-管理-图书、管理员-管理-读者、图书-属于-类别),全部转化为SQL Server 2000物理表:
- Reader实体→
user表:user_cardnumber为主键(VARCHAR(20)),user_state设CHECK约束('有效','挂失','注销'),user_registerdate设DEFAULTGETDATE()。 - Book实体→
book表:bannercode为主键(VARCHAR(30)),state设DEFAULT'在馆',pricenumber设DECIMAL(10,2)确保精度。 - 关系“读者-借阅-图书”→
borrow表:复合主键(user_cardnumber, bannercode, borrowdate),外键user_cardnumber引用user(user_cardnumber),外键bannercode引用book(bannercode),renew字段设DEFAULT'N'。 - 关系“图书-属于-类别”→
kind表(独立类别表):kindno为主键,book表中kindno为外键,禁止在book表中冗余存储kindname(避免更新异常)。
提示:所有外键必须启用级联删除(ON DELETE CASCADE)。例如删除
kind表中某分类,book表中kindno匹配的记录自动删除,否则ALTER TABLE book ADD CONSTRAINT FK_book_kind FOREIGN KEY (kindno) REFERENCES kind(kindno) ON DELETE CASCADE。
3.2 关键数据表SQL脚本与字段设计意图
以下为book、borrow、punishment三张核心表的创建脚本,每行注释说明设计意图:
-- book表:图书主信息,重点控制状态流转与价格精度 CREATE TABLE book ( bannercode VARCHAR(30) PRIMARY KEY, -- 图书唯一编号,业务主键(非自增ID) bookname VARCHAR(30) NOT NULL, -- 书名,NOT NULL确保基础信息完整 kindno VARCHAR(10) NOT NULL, -- 分类号,外键关联kind表 author VARCHAR(10), -- 作者,允许NULL(古籍作者佚名) publishing VARCHAR(30), -- 出版社,允许NULL(内部资料) publishtime DATE, -- 出版日期,DATE类型避免时间部分干扰 putintime DATE DEFAULT GETDATE(), -- 入库日期,默认当前日期 pricenumber DECIMAL(10,2) NOT NULL, -- 价格,DECIMAL保障财务计算精度 state VARCHAR(4) DEFAULT '在馆' -- 状态,DEFAULT确保新书入库即'在馆' ); GO -- 添加CHECK约束:state值域限定 ALTER TABLE book ADD CONSTRAINT CK_book_state CHECK (state IN ('在馆','借出','遗失','报废')); GO -- borrow表:借阅流水,核心是时间戳与状态联动 CREATE TABLE borrow ( user_cardnumber VARCHAR(20) NOT NULL, -- 读者证件号,外键 bannercode VARCHAR(30) NOT NULL, -- 图书编号,外键 borrowdate DATE NOT NULL DEFAULT GETDATE(), -- 借书日期,DEFAULT避免手动填错 receivedate DATE, -- 还书日期,NULL表示未还 renew CHAR(1) DEFAULT 'N', -- 是否续借,'Y'/'N',DEFAULT 'N' PRIMARY KEY (user_cardnumber, bannercode, borrowdate), FOREIGN KEY (user_cardnumber) REFERENCES user(user_cardnumber) ON DELETE CASCADE, FOREIGN KEY (bannercode) REFERENCES book(bannercode) ON DELETE CASCADE ); GO -- punishment表:罚款记录,依赖borrow表的receivedate计算 CREATE TABLE punishment ( user_cardnumber VARCHAR(20) PRIMARY KEY, -- 读者证件号,主键兼外键 sum_account DECIMAL(10,2) DEFAULT 0.00, -- 罚款总额,DECIMAL精度 last_update DATE DEFAULT GETDATE(), -- 最后更新时间,用于审计 FOREIGN KEY (user_cardnumber) REFERENCES user(user_cardnumber) ON DELETE CASCADE ); GO3.3 ADO连接封装:clsConnection类的健壮性设计与超时控制
VB6中ADO连接是最大翻车点。本方案clsConnection类强制实现以下机制:
- 连接字符串外置:从
conn.txt读取(如"Provider=SQLOLEDB;Data Source=.;Initial Catalog=LibraryDB;User ID=sa;Password=123;"),禁止硬编码在代码中。 - 连接池与超时:
getConnection()方法中设置myConn.ConnectionTimeout = 15(秒),超时抛出ERR_CONN_TIMEOUT。 - 状态双检:每次执行前检查
If myConn.State <> adStateOpen Then getConnection,避免重复Open导致内存泄漏。 - 错误隔离:
getDataReader(sql)方法中,Try...Catch捕获SQLException,记录err.Number & err.Description到日志文件,绝不让数据库错误弹窗暴露给用户。
关键代码段(VB6):
' clsConnection.cls Private strConn As String Private myConn As ADODB.Connection Public Sub getConnection() On Error GoTo ErrorHandler If myConn Is Nothing Then Set myConn = New ADODB.Connection If myConn.State <> adStateOpen Then ' 从外部文件读取连接字符串 Dim fso As New FileSystemObject Dim ts As TextStream Set ts = fso.OpenTextFile("F:\conn.txt", ForReading) strConn = ts.ReadLine ts.Close myConn.ConnectionString = strConn myConn.ConnectionTimeout = 15 ' 设置15秒超时 myConn.Open End If Exit Sub ErrorHandler: Err.Raise 5000, "clsConnection.getConnection", "数据库连接失败:" & Err.Description End Sub3.4 数据库安全加固:三类用户权限的最小化分配
SQL Server 2000中,不同角色必须使用独立登录账户,权限严格按需分配:
- 读者账户(reader_user):仅授予
SELECT权限于book、user、borrow(仅查自己记录)表;INSERT权限于borrow表(借书);UPDATE权限于borrow表的renew字段(续借)。 - 图书管理员账户(librarian_user):授予
SELECT/INSERT/UPDATE权限于borrow表;SELECT权限于book、user表;禁止DELETE权限(还书由系统自动更新receivedate)。 - 系统管理员账户(admin_user):授予
db_owner角色,但所有增删改操作必须通过存储过程(如sp_AddBook),禁止直接EXECUTE IMMEDIATE。
注意:
sp_AddBook存储过程中,必须包含IF EXISTS(SELECT 1 FROM book WHERE bannercode = @bannercode) BEGIN RAISERROR('图书编号已存在',16,1) RETURN END,将业务规则前置到数据库层。
4. 核心模块实现与避坑指南:借阅事务、续借逻辑与罚款计算的代码级落地
4.1 借阅功能:三步原子操作与库存强一致性保障
借书不是简单插一条borrow记录,而是涉及book表库存扣减、borrow表写入、user表已借数更新的原子操作。本方案在clsBorrowManager.BorrowBook()中实现:
' clsBorrowManager.cls Public Function BorrowBook(userCard As String, bookCode As String) As Boolean On Error GoTo ErrorHandler Dim conn As New ADODB.Connection Dim cmd As New ADODB.Command Dim rs As ADODB.Recordset ' 1. 开启事务 conn.ConnectionString = GetConnectionString() ' 从clsConnection获取 conn.Open conn.BeginTrans ' 2. 检查图书状态(必须'在馆') Set cmd.ActiveConnection = conn cmd.CommandText = "SELECT state, pricenumber FROM book WHERE bannercode = ?" cmd.Parameters.Append cmd.CreateParameter("@code", adVarChar, adParamInput, 30, bookCode) Set rs = cmd.Execute If rs.EOF Or rs.Fields("state").Value <> "在馆" Then conn.RollbackTrans BorrowBook = False Exit Function End If ' 3. 扣减库存(UPDATE book SET state='借出' WHERE bannercode=?) cmd.CommandText = "UPDATE book SET state='借出' WHERE bannercode = ?" cmd.Parameters.Refresh cmd.Parameters.Append cmd.CreateParameter("@code", adVarChar, adParamInput, 30, bookCode) cmd.Execute ' 4. 写入borrow记录 cmd.CommandText = "INSERT INTO borrow (user_cardnumber, bannercode, borrowdate) VALUES (?, ?, GETDATE())" cmd.Parameters.Refresh cmd.Parameters.Append cmd.CreateParameter("@user", adVarChar, adParamInput, 20, userCard) cmd.Parameters.Append cmd.CreateParameter("@book", adVarChar, adParamInput, 30, bookCode) cmd.Execute ' 5. 更新读者已借数(user表user_borrowed字段) cmd.CommandText = "UPDATE user SET user_borrowed = user_borrowed + 1 WHERE user_cardnumber = ?" cmd.Parameters.Refresh cmd.Parameters.Append cmd.CreateParameter("@user", adVarChar, adParamInput, 20, userCard) cmd.Execute ' 6. 提交事务 conn.CommitTrans conn.Close BorrowBook = True Exit Function ErrorHandler: If Not conn Is Nothing Then If conn.State = adStateOpen Then conn.RollbackTrans conn.Close End If Err.Raise Err.Number, "clsBorrowManager.BorrowBook", "借书失败:" & Err.Description End Function设计说明:
- 事务必须显式
BeginTrans/CommitTrans,禁止依赖ADO默认行为(VB6中默认不开启事务)。 - 库存检查与更新分离:先
SELECT确认状态,再UPDATE,避免UPDATE ... WHERE state='在馆'返回0行时无法感知失败。 user_borrowed字段在user表中维护,不通过COUNT(*) FROM borrow WHERE user_cardnumber=? AND receivedate IS NULL实时计算(性能差),这是典型的“空间换时间”设计。
4.2 续借功能:时间窗口校验与状态机驱动
续借不是重置receivedate,而是更新renew字段并延长归还期限。本方案定义续借规则:仅允许借出后30天内、且未超期的图书续借一次。clsBorrowManager.RenewBook()实现:
' 续借逻辑:更新renew='Y',并设置新的应还日期(当前日期+30天) Public Function RenewBook(userCard As String, bookCode As String) As Boolean On Error GoTo ErrorHandler Dim conn As New ADODB.Connection Dim cmd As New ADODB.Command conn.ConnectionString = GetConnectionString() conn.Open conn.BeginTrans ' 1. 检查是否已续借(renew='Y'则拒绝) cmd.ActiveConnection = conn cmd.CommandText = "SELECT renew FROM borrow WHERE user_cardnumber = ? AND bannercode = ? AND receivedate IS NULL" cmd.Parameters.Append cmd.CreateParameter("@user", adVarChar, adParamInput, 20, userCard) cmd.Parameters.Append cmd.CreateParameter("@book", adVarChar, adParamInput, 30, bookCode) Dim rs As ADODB.Recordset Set rs = cmd.Execute If Not rs.EOF Then If rs.Fields("renew").Value = "Y" Then conn.RollbackTrans RenewBook = False Exit Function End If Else conn.RollbackTrans RenewBook = False Exit Function End If ' 2. 检查借出时间是否在30天内(DATEDIFF(day, borrowdate, GETDATE()) <= 30) cmd.CommandText = "SELECT DATEDIFF(day, borrowdate, GETDATE()) AS days FROM borrow WHERE user_cardnumber = ? AND bannercode = ? AND receivedate IS NULL" cmd.Parameters.Refresh cmd.Parameters.Append cmd.CreateParameter("@user", adVarChar, adParamInput, 20, userCard) cmd.Parameters.Append cmd.CreateParameter("@book", adVarChar, adParamInput, 30, bookCode) Set rs = cmd.Execute If rs.EOF Or rs.Fields("days").Value > 30 Then conn.RollbackTrans RenewBook = False Exit Function End If ' 3. 更新renew字段并设置新应还日期(借出日+60天) cmd.CommandText = "UPDATE borrow SET renew = 'Y', receivedate = DATEADD(day, 60, borrowdate) WHERE user_cardnumber = ? AND bannercode = ? AND receivedate IS NULL" cmd.Parameters.Refresh cmd.Parameters.Append cmd.CreateParameter("@user", adVarChar, adParamInput, 20, userCard) cmd.Parameters.Append cmd.CreateParameter("@book", adVarChar, adParamInput, 30, bookCode) cmd.Execute conn.CommitTrans conn.Close RenewBook = True Exit Function ErrorHandler: If Not conn Is Nothing Then If conn.State = adStateOpen Then conn.RollbackTrans conn.Close End If Err.Raise Err.Number, "clsBorrowManager.RenewBook", "续借失败:" & Err.Description End Function参数说明:
DATEADD(day, 60, borrowdate):新应还日期=原借出日+60天(非当前日+30天),确保读者有固定归还周期。renew = 'Y':作为状态标记,供罚款计算模块识别“已续借图书”。
4.3 罚款计算:触发器驱动的自动化与人工复核接口
罚款不应由应用层计算,而应由数据库触发器实时维护。本方案在borrow表上创建trg_UpdatePunishment触发器:
-- 创建罚款触发器:当receivedate被更新(还书)时自动计算 CREATE TRIGGER trg_UpdatePunishment ON borrow AFTER UPDATE AS BEGIN IF UPDATE(receivedate) BEGIN DECLARE @user_cardnumber VARCHAR(20) DECLARE @borrowdate DATE DECLARE @receivedate DATE DECLARE @days INT DECLARE @fine DECIMAL(10,2) SELECT @user_cardnumber = i.user_cardnumber, @borrowdate = i.borrowdate, @receivedate = i.receivedate FROM inserted i -- 计算超期天数(receivedate - borrowdate - 30天宽限期) SET @days = DATEDIFF(day, @borrowdate, @receivedate) - 30 IF @days > 0 BEGIN SET @fine = @days * 0.5 -- 每超期1天罚0.5元 -- 更新punishment表,若不存在则INSERT,存在则UPDATE IF EXISTS(SELECT 1 FROM punishment WHERE user_cardnumber = @user_cardnumber) UPDATE punishment SET sum_account = sum_account + @fine, last_update = GETDATE() WHERE user_cardnumber = @user_cardnumber ELSE INSERT INTO punishment (user_cardnumber, sum_account, last_update) VALUES (@user_cardnumber, @fine, GETDATE()) END END END GO设计说明:
- 触发器在
AFTER UPDATE执行,确保receivedate已写入。 - 宽限期30天硬编码在触发器中,与应用层续借逻辑(+30天)保持一致,避免规则分散。
punishment表提供sp_ManualAdjustPunishment(@user, @amount)存储过程,供管理员人工调整(如读者证明不可抗力),所有人工操作必须写入log表。
4.4 常见问题排查:借阅失败、续借无效、罚款不更新的5个血泪坑
现象1:借书时提示“图书状态异常”,但book表中state显示‘在馆’
原因:SELECT state FROM book WHERE bannercode = ?查询时,bannercode参数长度超过30字符,SQL Server自动截断,导致查不到记录。
解决:VB6中cmd.Parameters.Append cmd.CreateParameter("@code", adVarChar, adParamInput, 30, bookCode)的第三个参数(长度)必须与表定义完全一致(30),且传入的bookCode变量需用Left$(bookCode, 30)截断。
现象2:续借操作成功,但还书后罚款仍按原30天计算
原因:触发器中DATEDIFF(day, @borrowdate, @receivedate) - 30未考虑续借情况,应改为DATEDIFF(day, @borrowdate, @receivedate) - CASE WHEN renew='Y' THEN 60 ELSE 30 END。
解决:修改触发器,从inserted表中读取renew字段值:SELECT @renew = i.renew FROM inserted i,并在计算中加入分支。
现象3:多用户同时借同一本书,出现库存扣为负数
原因:未加事务隔离级别,两个会话并发执行SELECT state均返回‘在馆’,然后都执行UPDATE state='借出'。
解决:在SELECT语句后加WITH (UPDLOCK, HOLDLOCK)提示:SELECT state FROM book WITH (UPDLOCK, HOLDLOCK) WHERE bannercode = ?,强制行锁。
现象4:ADO连接报错“未找到提供程序”,但conn.txt路径正确
原因:SQL Server 2000客户端未安装,或VB6工程中未引用Microsoft ActiveX Data Objects 2.8 Library。
解决:在VB6 IDE中,Project → References勾选Microsoft ActiveX Data Objects 2.8 Library;若提示缺失,需安装MDAC_TYP.EXE(Microsoft Data Access Components)。
现象5:罚款金额小数位丢失(如1.5元存为1元)
原因:punishment.sum_account字段定义为INT或FLOAT,而非DECIMAL(10,2)。
解决:ALTER TABLE punishment ALTER COLUMN sum_account DECIMAL(10,2),并检查所有INSERT/UPDATE语句中数值是否用CONVERT(DECIMAL(10,2), @value)显式转换。
5. 文档交付与答辩验收:从需求规格说明书到测试用例表的完整清单
5.1 软件工程文档包结构:8份文档的命名规范与内容要点
本方案交付的文档包严格遵循GB/T 8567-2006《计算机软件文档编制规范》,共8份文档,命名与核心内容如下:
| 文档名称 | 文件名 | 必含内容要点 | 页数要求 |
|---|---|---|---|
| 可行性研究报告 | SRS_Feasibility.doc | 技术可行性(VB6+SQL2000成熟度分析)、经济可行性(开发成本<500元)、操作可行性(Windows XP及以上即可运行) | ≥3页 |
| 需求规格说明书 | SRS_Requirements.doc | 用例图7张(读者/管理员/系统管理员各1张,扩展用例2张)、时序图7张(对应核心流程)、数据字典(8张表字段说明,含类型、长度、约束、示例值) | ≥15页 |
| 概要设计说明书 | SDD_Architecture.doc | 三层架构图(标注各层组件名)、模块划分表(6个VB6类名、职责、输入输出)、数据库E-R图(Visio绘制,含实体属性、关系基数) | ≥10页 |
| 详细设计说明书 | DDD_Detailed.doc | 类图6张(含属性/方法/可见性)、关键算法描述(如罚款计算公式、续借时间窗逻辑)、界面原型图(VB6窗体截图+控件ID说明) | ≥20页 |
| 数据库设计说明书 | DDS_Database.doc | 8张表SQL脚本(含CREATE TABLE、CONSTRAINT、INDEX)、外键关系图(PowerDesigner导出)、安全策略(三类用户权限表) | ≥12页 |
| 测试计划 | TP_TestPlan.doc | 测试范围(覆盖所有用例)、测试环境(WinXP+SQL2000+VB6 Runtime)、通过标准(用例执行率100%,缺陷修复率100%) | ≥5页 |
| 测试用例表 | TC_TestCase.xls | Excel表格:用例ID、标题、前置条件、输入步骤、预期结果、实际结果、状态(Pass/Fail)。例如TC-001:“读者借书-库存不足”,前置条件“book表state='借出'”,预期“弹出提示‘图书已被借出’” | ≥50条 |
| 用户手册 | UM_UserManual.doc | 分角色操作指南(读者:如何查书/借书;管理员:如何添加图书;系统管理员:如何重置密码)、常见问题FAQ(含现象/原因/解决,如“登录失败”对应conn.txt路径错误) | ≥8页 |
提示:所有文档中的图表必须编号(如“图3.1 系统E-R图”、“表4.2 borrow表字段说明”),并在正文中引用。答辩时老师必问“这张图对应哪段代码”,务必提前标注好(如“图2.3 读者用例图 → frmReaderQuery.vbp中txtSearch事件调用clsSearchEngine”)。
5.2 答辩演示技巧:3分钟讲清“为什么你的设计比别人更工程化”
答辩不是功能演示,而是展示工程思维。我通常用这3分钟结构:
第一分钟:锚定需求痛点
“老师好,本系统解决的核心问题是图书管理中的状态一致性。比如借书时,必须同时更新book表state、borrow表记录、user表已借数——漏掉任何一步都会导致数据错乱。我的设计用事务封装+触发器+CHECK约束三重保障,确保这三步要么全成功,要么全失败。”第二分钟:亮出设计证据
“请看这份《详细设计说明书》第12页,clsBorrowManager.BorrowBook()方法的伪代码,它严格按UML时序图的7步执行;再看《数据库设计说明书》第8页,book表的state字段有CHECK (state IN ('在馆','借出','遗失','报废'))约束,从数据库层堵死非法状态。”第三分钟:预判质疑并反证
“可能有老师问:为什么不用MySQL或Java?因为VB6+SQL2000的技术栈透明度最高——ADO连接字符串、SQL语句、事务控制全部可见可控,没有Spring Boot的自动配置黑匣子。这恰恰符合软件工程课设的目标:让设计决策可追溯、可验证、可答辩。”
关键动作:演示时打开TC_TestCase.xls,随机选一个Fail用例(如TC-023“管理员删除在借图书”),现场展示sp_DeleteBook存储过程中IF EXISTS(SELECT 1 FROM borrow WHERE bannercode=@code AND receivedate IS NULL)的防护逻辑,并指出该用例在《测试报告》中已标记为Pass。
5.3 验收检查清单:答辩前必须逐项核对的12个硬指标
这份清单是我带学生答辩前强制执行的“通关 checklist”,少一项都可能被质疑工程素养:
| 序号 | 检查项 | 合格标准 | 不合格后果 |
|---|---|---|---|
| 1 | 用例图完整性 | 三类参与者(读者/图书管理员/系统管理员)各1张主用例图,且含<<include>>/<<extend>>关系线 | 用例图缺失关系线 → 被质疑需求理解不深 |
| 2 | 时序图与代码对应 | 任选1张时序图(如“管理员添加图书”),能当场指出VB6中哪个方法调用对应图中第几步 | 无法对应 → 被质疑设计与实现脱节 |
| 3 | 数据库字段约束 | book.state、borrow.renew、user.user_state均有CHECK约束,punishment.sum_account为DECIMAL | 缺少CHECK → 被质疑数据质量意识薄弱 |
| 4 | 事务控制显式化 | BorrowBook()、RenewBook()等方法中,BeginTrans/CommitTrans/RollbackTrans三者齐全 | 仅用BeginTrans→ 被质疑异常处理能力 |
| 5 | 连接字符串外置 | conn.txt文件存在,且VB6代码中fso.OpenTextFile("F:\conn.txt")路径可访问 | 硬编码连接串 → 被质疑配置管理能力 |
| 6 | 测试用例覆盖率 | TC_TestCase.xls中,借阅/续借/还书/罚款/管理员操作五类场景,每类≥8条用例 | 总数<40条 → 被质疑测试深度不足 |
| 7 | 错误处理统一化 | 所有Err.Raise语句格式为Err.Raise 5000, "模块名.方法名", "描述",且《用户手册》FAQ中有对应解答 | 错误码混乱 → 被质疑可维护性 |
本文还有配套的精品资源,点击获取