本章精髓 做完和交出去之间还隔着一段路。这段路上要处理的都不是功能:别人打不打得开、出错时给不给得出看得懂的提示、里面还有没有编造的内容和调试残留、丢了能不能找回来。功能是做给自己看的,这些是做给别人看的。
学完本章后,你应该能够:
- 说清版本号三段各自的含义,并判断一次改动该升哪一段;
- 按七类边界情况逐条测试一件作品,并记录每一类的实际结果;
- 把含糊的验收标准改写成能用是或否判断的用例,并识别"换一个形容词"这种假改写;
- 找出交付物里的占位内容、调试残留与未经要求的功能;
- 按 3-2-1 完成一次备份并恢复验证,再用三段话把作品演示给别人。
一件样例 · 三行错误显示 · 六类检查
本章不产出新作品,只把已有的作品检查一遍再交出去。
1.1本章做的是检查,不是开发
作品的功能到这一步应当已经跑通了。本章处理的是另一类事情:作品从你手上转移到别人手上时,会暴露出来的那些问题。这些问题在自己机器上、用自己的数据、由自己操作时,一个也碰不到。
课上先拿一件样例作品做示范,用六类检查逐条过一遍,把里面的问题挑出来。之后的时间用于检查自己的期末作品并完成交付。
1.2一件看起来做完了的作品
样例是一个活动报名统计工具:输入活动名称和人数,点添加,下面自动出合计。功能是齐的,界面也整洁,照常规用法跑一遍挑不出毛病。
问题要换一种用法才看得见。下面三行是把它交给另一个人之后,屏幕上真实出现过的内容:
三种情况程序都没有报错,界面照常显示,只是显示的内容不对。这件作品一共有十处问题,本节课要把它们全部找出来。打开 第16章演示_找十处.html,那件样例就在里面,可以当堂点着找。
1.3六类检查
问题不是靠一条条想出来的,是靠一张固定的表逐类走出来的。本章用的六类如下,配套的 第16章演示_交付自检表.md 可以直接拿去填。
| 检查类别 | 回答的问题 | 最常被漏掉的一条 |
|---|---|---|
| 版本号与署名 | 别人拿到的是哪一版,出问题找谁 | 程序里的版本号与说明文件对不上 |
| 边界情况 | 不按你的预期用,会发生什么 | 只有一条记录时 |
| 验收用例 | 怎么判断这件作品算不算做好了 | 标准里还留着形容词 |
| 交付前清理 | 里面还有没有不该出现的东西 | 没人要求过的多余功能 |
| 回归检查 | 改完一处,别处还好不好 | 只改一处时就没重跑 |
| 备份 | 丢了能不能找回来 | 备份从没验证过能不能恢复 |
1.4本章新技巧:让它挑刺,不让它夸
把作品交给大模型看,得到的多半是一段肯定,后面跟几条温和的建议。这个语气对写作品的人是舒服的,对交作品的人没有用。你需要的是把答辩现场会被问到的问题,提前在没人看见的时候问一遍。
做法是给它一个明确的角色和两条禁令:只挑毛病,不写优点;只给问题清单,不给改好的版本。第二条尤其要紧,拿到改好的版本,你就跳过了"原来错在哪"这一步,下次同类问题照样看不出来。
1.5可直接复制的提示词
三段提示词里的几条要求,分别对应后面要讲的知识点:
1.6大模型的常见偏差
先夸一段再说问题。 开头半屏是肯定,问题藏在后面,语气还偏温和。要求里写明"不要写优点",它才会直接进入正题。
直接把改好的版本交给你。 这是本章最需要防的一种。改好的版本看着省事,代价是你不知道原来错在哪,也无法判断它改的对不对。"不要给我改好的版本,我自己改"必须写。
只挑文字,不数交付物。 它擅长指出说明写得不清楚,不擅长发现你少交了数据文件或者没有备份。所以"交付物还缺什么"要单独列成一条问出来。
列边界情况时只列合理输入。 不给它"想把程序用坏"这个角色,它列的都是正常操作的变体。真正会出事的是愚蠢的和恶意的用法,而这两类它不会主动想到。
第16章演示_找十处.html 把样例作品与十处问题的清单放在同一页,点一处对一处,可以直接当堂用。三段数字 · 七类边界 · 换个人判 · 回归
本章的核心内容集中在这一部分和下一部分。
这八个术语会原样出现在版本说明、测试记录与运维规范里。前四个在本部分讲解,后四个在第三部分讲解。
2.1四个知识点,一个一个看
第一段是 0 表示尚未稳定,交出去的作品应当是 1.0.0
现象:程序标题栏写着 v1.0,说明文件里写着 v0.3。
概念:语义化版本把版本号定成三段:主版本、次版本、修订号。修了缺陷而用法不变,加第三段;加了功能而原来的用法仍然可用,加第二段;改动使原来的用法失效,加第一段并把后两段清零。版本号是给别人的承诺,不是自己的流水号。
类比:教材的第几版第几次印刷。改版说明内容变了,重印只是多印一批。
标出的这一类最常被漏掉
现象:录一条正常数据一切正常,什么都不填点添加,列表里多出一条空记录。
概念:边界情况(edge case)指正常范围的两端与外面。自己用碰不到,交给别人就会碰到,因为别人不知道你预设的范围在哪里。七类中最常被漏掉的是"只有一条":按多条写的连接词和分隔符,在只有一条时往往读不通,样例作品里那句"已录入 和 读书会"就是这么来的。
类比:门锁要试的是没带钥匙和拿错钥匙的时候,不是有钥匙的时候。
三段齐了才算一条用例
现象:验收标准写着"界面友好""运行稳定""兼容性良好"。
概念:验收用例的格式是:在什么情况下,做什么操作,应该出现什么结果。判断它写得合不合格只有一条标准:换一个人照着做,能不能得到同一个是或否。"界面友好"做不到,两个人的判断可能相反。验收的目的是消除分歧,形容词把分歧原样留在了那里。
类比:验收合同不写"质量好",写"误差不超过 2 毫米"。
样例作品里真实存在的一处回归
现象:加完新功能,原来能用的那个不能用了。
概念:原本正常的功能因一次改动而失效,称为回归(regression)。它多数发生在你以为无关的地方:两个功能共用了一段代码、共用了同一个数据文件、共用了同一个样式类。防的办法只有一个,改完之后把之前验过的用例照原样再走一遍。用例要写成一张固定的表,照表走,不要凭记忆想想哪些该重试。
类比:修完一处水管,把每个龙头都开一遍再走。
2.2把含糊的验收标准改写成可判断的
样例作品的说明文件里列了五条验收标准,一条也用不了。左边是原文,右边是改写之后的:
| 原文 | 问题出在哪 | 改写之后 |
|---|---|---|
| 界面友好,操作简单 | 两个人的判断可能相反 | 打开程序不做任何操作时,界面上能看到下一步该点哪个按钮 |
| 数据统计准确 | 没说拿什么去对 | 录入说明文件示例中的三条数据,合计显示 75 |
| 运行稳定,不闪退 | 没说多久算稳定 | 连续执行同一操作十次,十次结果相同,程序没有退出 |
| 兼容性良好 | 没说和什么兼容 | 在另一台从未装过本程序的计算机上打开,功能与本机一致 |
| 用户体验流畅 | 流畅没有量 | 点击查询后三秒内出现结果 |
自查的办法很简单:把验收标准逐条读一遍,凡是出现"友好、简单、流畅、合理、良好、准确"这类词,而后面没有跟上具体数值或具体操作的,都要改写。
调试残留 · 多余功能 · 3-2-1 · 开发记录
这一部分处理的是交付物里那些"不该出现"和"必须存在"的东西。
3.1另外四个知识点
第三类要靠对照功能清单数按钮
现象:界面下方还留着"联系人:张三 13800138000"。
概念:交付前要清掉三类东西:占位内容(示例姓名、假电话、测试邮箱)、调试残留(打印输出、注释掉的旧代码、填测试数据的按钮)、未经要求的功能。前两类的害处是被人当真,以及暴露本机的路径与用户名。用全文搜索比用眼睛找可靠得多,因为你已经看过这份代码几十遍了。
类比:交房之前把墙上的施工标记擦掉。
这条线要自己画一个日期出来
现象:答辩前一晚"就加一个小功能,五分钟就好",然后到深夜还在修别处。
概念:功能冻结指定下一个日期,此后只修缺陷、不加功能。理由有两层:改动会牵动别处,五分钟往往变成半小时;更要紧的是,新加的功能是交付物里唯一没有验收标准覆盖的部分,出了问题你不知道该怎么修,也不知道该不该修。冻结之后做最后一次完整验证,然后以那一份为准,不再改动。
类比:付印之前的清样。到这一步只能捉错字,不能重写段落。
还有一条:没验证过的备份不算备份
现象:作品只存在自己这一台电脑上。
概念:通行的备份准则叫 3-2-1:三份副本、两种不同介质、至少一份不在身边。三个数字各挡一类事故,不是凑出来的。除此之外还有一条容易被跳过的:没有验证过的备份不算备份。把文件从备份里取出来打开一次,确认能用,这一步不做,多数人是在真正需要恢复的那一天才发现压缩包是坏的。
类比:论文只存一处的人,后来都学会了用云盘。
只写成功不写卡点,等于交了一份没有内容的记录
现象:开发记录写成了一段感想。
概念:开发记录记的是过程,每条写三样:遇到什么现象、判断是什么原因、怎么改的。评委看的正是你怎么处理问题的,顺利的部分反而没有信息量。这份记录同时也是你的作品集素材:全学期五件作品攒成一页,每件写清做什么、给谁用、走哪条路线。
类比:病历记的是症状、诊断、处置,不是"病人恢复良好"。
3.2样例作品的代码:一行一行找问题
下面是样例作品中负责添加和显示的两段代码,原样抄录。它能跑,功能也对,问题全在正常用法之外。
function addItem() {
var name = document.getElementById('name').value;
var count = Number(document.getElementById('count').value);
items.push({ name: name, count: count });
console.log('添加了一条', name, count, items);
render();
}
function render() {
var sum = 0;
for (var i = 0; i < items.length; i++) {
…
sum = sum + items[i].count;
}
var names = items.map(function (it) { return it.name; });
var joined = names.slice(0, -1).join('、') + ' 和 ' + names[names.length - 1];
document.getElementById('total').textContent =
'已录入 ' + joined + ',共 ' + items.length + ' 项,合计 ' + sum + ' 人。';
console.log('当前合计', sum);
}
这六处里,前四处属于边界情况,第五处属于调试残留,第六处同时属于多余功能与回归。没有一处是功能写错了,它们都是在"正常用法"之外才出现的。
六类逐条走 · 十处问题 · 三段话
拿样例作品当靶子,把六类检查完整走一遍。
4.1演示步骤
4.2样例作品的十处问题
全部找出来之后对照一遍。十处分属六类,没有一处是功能写错了。
| # | 问题 | 属于哪一类 |
|---|---|---|
| 1 | 标题栏 v1.0,说明文件 v0.3 | 版本号 |
| 2 | 程序与说明里都没有作者和日期 | 署名 |
| 3 | 只录一条时显示"已录入 和 读书会" | 边界情况 |
| 4 | 什么都不填点添加,多出一条空记录 | 边界情况 |
| 5 | 人数填汉字,合计变成 NaN | 边界情况 |
| 6 | 页脚的"张三 13800138000" | 占位内容 |
| 7 | 「填入测试数据」按钮与控制台调试输出 | 调试残留 |
| 8 | 「一键美化」按钮不在任何需求里 | 多余功能 |
| 9 | 点美化之后合计整行消失 | 回归 |
| 10 | 刷新页面数据全部丢失,也没有导出 | 备份 |
4.3答辩:三段话,不逐个介绍功能
把作品讲给别人听,顺序也是固定的:
4.4前沿三分钟:一个能被程序读懂的承诺
每章固定栏目 · 一条与本章内容相关的行业动态
早年的版本号相当随意。有的按年份命名,有的按发布次数排,有的干脆叫"最终版",然后是"最终版2"。使用者拿到一个新版本,无从判断能不能直接换上去。二〇一三年,语义化版本规范把三段数字的含义定死,此后逐渐成为通行做法。
这套约定之所以有用,是因为它是一个能被程序读懂的承诺。现在的软件包管理工具允许开发者写下"可以自动升到 1.x 的任何版本,但不要升到 2.0"这样的规则,工具据此自动决定要不要更新某个依赖。这条规则之所以成立,靠的正是那个约定:按照约定,1.x 之间不会改变用法,2.0 会。
对期末交付的实际影响有一条:版本号不是流水号,是给拿到作品的人的一句话。写成 1.0.0,等于说"这一版的用法定下来了";写成 0.3,等于说"还会变,别指望"。写哪个,要看你交出去的是哪一种。
六类自检 · 一次恢复 · 三段演示
上机环节由此开始,当堂完成、当堂提交并现场答辩。
5.1三个题目,任选其一
本章的任务只有一件:把自己的期末作品按六类检查一遍,改完,交出去,然后做现场演示。作品本身在第 15 章已经开题,这里三选一的是你要重点补齐的那一块。
七类边界逐条实测,验收标准全部改写成可判断的用例。
功能已完整的选这条说明文件五部分补齐,清理占位内容与调试残留,做一次他机验收。
交付物不齐的选这条定下冻结日期做最后一次完整回归,按 3-2-1 备份并恢复验证。
改到最后一刻的选这条三条重点只是分配时间的建议,六类检查一类都不能省。时间实在紧张时,有两类排在最前:边界情况与恢复演练。前者决定别人能不能用起来,后者决定东西丢了还在不在。
5.2上机六步
5.3共同验收标准
5.4常见错误与处理
5.5提交内容
提交方式:按教师提供的作业模板填写。提交渠道见课堂通知,当堂提交并现场答辩。
5.6再进一步(选做)
选做一 把自检表改成你自己的。删掉与你这件作品无关的行,补上它特有的检查项。补的时候会发现一件事:你补上的每一条,几乎都对应着你这学期真正踩过的一个坑。一份用久了的自检表长什么样,取决于这个人做坏过什么。这也是它比任何通用清单都管用的原因。
选做二 攒一个个人技能包。一个 .md 文件,把这学期用顺手的提示词、约束句、检查表都收进去,每条写三样:什么时候用、原文是什么、用了之后效果如何。期中起草的那一版是 v0.5,期末定版 v1.0,随作品集一起提交。这份文件比任何一件作品都跟得久,因为它记的是你的做法,不是某一次的产物。
本章五条结论
- 交付前要查的都不是功能。版本号、边界情况、验收用例、清理、回归、备份,六类逐条走,靠表不靠印象。
- 边界情况自己碰不到,别人一用就碰到。七类里最常漏掉的是"只有一条",因为按多条写的文字在一条时读不通。
- 验收标准里有形容词,就等于没有验收标准。检验办法是换一个人照着判,看能不能得到同一个是或否。
- 没有验证过的备份不算备份。从备份里恢复一次,这一步最常被跳过,也是备份失效最常见的原因。
- 报错会停下来,不报错但结果不对不会。这门课从第六章讲到这里的那一条,到交付这一步仍然成立。
结课:手上的操作越来越少,判断的分量越来越重
回头看这十六章,你亲手敲的代码几乎没有增加,能交出去的东西却从一张名片变成了一件带数据库、能打包、能被陌生人独立用完的软件。中间变化的不是你的打字速度,是你在整件事里担的角色。
第一阶段你是打字员:把想法说出来,看它变成东西。第二阶段你是产品经理:先写清楚要什么,再让它去做,因为你发现说不清的部分它会替你决定。到这一章你是验收官:功能它写,对不对由你判,而判的依据是你自己定下来的那几条标准。
执行可以委托,定义与验收不能。这句话在第一章就写在那里,当时它只是一句话;走完十六章之后,你手上应该已经有了一整套让它成立的做法:需求单、验收标准、预演、抽查三条、他机验收、自检表。这些东西看起来琐碎,但它们是你与一个能写任何代码的工具之间,真正属于你的那一部分。
打开 第16章演示_角色三变.html,把这十六章里"你做的"与"它做的"并排看一遍。这一页也可以直接放进你的作品集。