本节摘要:系统上线不是开发的结束,而是"变更管理"的开始。这一节解决三个最实际的问题:改东西怎么改才不出乱子(版本号与发布流程)、出了错怎么第一时间知道(错误日志表)、新同事怎么快速接得住(验收清单与培训路径)。掌握它们,你的系统能伴随业务平安长大三五年。
上一节建立的备份日历管的是"不变的日子",这一节管"变动的日子"。业务会变:订单要多记一个运单号,报表要加一列税率,仓库要新来一位录入员。每一次变动都是一次小型手术,没有流程的手术靠运气,有流程的手术靠 checklist。
先立一条铁规矩:每一个前端文件都有版本号,且能被程序自己报出来。 华彩项目的前端统一命名为形如"华彩前端_v2.3.1"的名字,三段数字分别代表大改版、加功能、修缺陷。光靠名字还不够——实际运行中的那份文件到底是不是它声称的版本,得让程序说了算。
做法很朴素:建一张只有一行数据的系统表,随每次发布更新:
-- 后端里的一行小表,专供版本对号 CREATE TABLE usysAppInfo ( AppVersion TEXT 10, -- 当前配套前端版本 ReleasedOn DATETIME, -- 发布日期 ReleaseNote TEXT 255 -- 本次改动一句话 );
前端启动窗体加载时读这张表并把自己的编译版本号与之比对,不一致就弹提示让用户找管理员取新版。这个十行以内的小机关,替我们拦住了"老前端连新后端、字段对不上号"这类最烦人的事故。检索它的代码只需要一句 DLookup:
' 启动时核对前后端版本是否匹配 Dim vBackend As String vBackend = Nz(DLookup("AppVersion", "usysAppInfo"), "?") If vBackend <> "v2.3.1" Then MsgBox "后端已是 " & vBackend & ",你手上这份前端太旧了。" & vbCrLf & _ "请到共享目录【发版】文件夹取最新前端。", vbExclamation, "版本不符" End If
用一次真实的结构变更把流程走完整。第五个月,客服主管提出:快递员揽件后要把运单号回填进订单,方便对账。
第一步,评估影响面。 打开后端的关系图和前端的导航菜单,逐个排查谁引用了 tblOrder:直接以订单表做数据源的查询 7 个,其中 2 个被窗体用、1 个被月度报表用;tblShipment 发货表其实已经存在,运单号语义上属于发货而非订单本体——这判断值半小时,避免了把字段放错的返工。
第二步,定方案与窗口期。 结论是在 tblShipment 加 TrackingNo 短文本字段,配一段录入校验。变更属于"后端结构级",必须安排在午休无人录入的时段执行,前一天先把当周备份多存一份。
第三步,执行与验证。 独占方式打开后端(第 7.2 节拆分后的习惯动作),设计视图加字段保存,随后立即跑三条验证:空表状态下追加一条带运单号的测试数据;把用到的三个窗体各刷新一遍确认绑定正常;月度报表预览不出错。全部通过后在变更日志里记一笔。
第四步,发布前端。 若本次也改了前端(比如在发货窗体加了文本框),就把改好的 accdb 编译生成 accde,按版本规则改名放入共享目录【发版】文件夹,通知三位使用者关闭旧版重新取用。整个过程四十分钟,业务零感知。
| 变更级别 | 典型例子 | 操作窗口 | 需要的动作 |
|---|---|---|---|
| 前端级 | 改按钮文字、调报表样式 | 随时 | 替换前端文件即可 |
| 后端结构级 | 加字段、加关系 | 无人录入时段 | 备份先行、独占打开、跑验证清单 |
| 环境级 | 换共享目录、重装 Office | 下班后 | 同步更新链接表管理器路径 |

小系统的开发者不在现场,用户遇到报错的第一反应常是"随便点点就过去了",等发现时问题已攒了一堆证据流失。所以第二件武器是强制性的错误日志。建一张专用表,然后在每个关键过程的错误分支里都留下痕迹:
' 通用日志函数:出错处一律调用它,禁止无声吞掉 Public Sub LogError(ModuleName As String, Extra As String) On Error Resume Next ' 日志函数自身不许再抛错 Dim db As DAO.Database Set db = DBEngine(0)(0) db.Execute "INSERT INTO usysErrorLog " & _ "(ErrNum, ErrDesc, ModuleName, CurUser, Extra) VALUES ('" & _ Err.Number & "', '" & Replace(Err.Description, "'", "''") & "', '" & _ ModuleName & "', '" & Environ$("USERNAME") & "', '" & Extra & "')", dbFailOnError End Sub
字段只留五样最有用的:错误号、描述、所在模块、操作者、补充上下文。每月扫一眼这张表,高频错误就是优化方向的排行榜——华彩项目靠它发现出库窗体有一个必现的类型转换错误,源头是扫码枪偶发输入了字母,十分钟就补上了校验。拒绝 On Error Resume Next 式的沉默,是业余与专业之间真正的分界线。
最后一公里是人的交接。华彩的做法沉淀成两件套,后来被我们用在所有项目上:
一张验收用例表。 上线前拉着业务代表逐行过:前置条件、操作步骤、预期结果、实测结论四列,测试记录本身就用 Access 的一张表存放。二十几行用例覆盖不到两小时,但它把"我觉得好了"变成"每条都验过了",签收从此有据可查。
一段十五分钟上手路径。 新员工入职当天,由一位熟练同事带着只练四件事:登录后看到的主界面、录一张单、查一件货的历史、打印本周汇总。其余功能让使用者在需要时自己撞见——培训的目标不是讲完全部功能,而是建立"我不怕点坏它"的信心。配合 7.1 节的安全设置(普通账号本就没有删除权),这种信心是有底气的,不是盲目乐观。
运维交接的质量取决于三份活文档是否随版本活着。变更日志:一行一次变更,日期、级别、内容、执行人四列,与代码同命运;应急手册:单页纸写清打不开库怎么办、备份在哪、找谁——给半夜值班的非技术人员看的,语言要像便利贴不像论文;权限台账:谁能碰后端、谁有全部前端、密码托管在何处。三件套更新时机都绑定在同一件事上:每次发版动作的最后一步。写在流程末尾的制度才活得过三个月。
最后补一条容易被遗忘的邻线约定:迭代节奏本身也要有节律。华彩的经验是"每月一版封顶,紧急修复不限但必须走热修通道"——固定的发版日让使用者形成预期,也让你的变更日志看起来像编年史而不是流水账。纪律到这一步,系统才真正拥有了与其业务一同成长的体质。
下一章是全书的收官:钻进引擎舱看看这套系统为什么这样运转,再把目光投向三年五年之后的路。