把人工经验写成脚本需求时,例外情况不能只写“特殊情况特殊处理”,而要写成可判定、可执行、可回退的分支:先固定正常流程的输入与输出,再为每个已知例外写明触发条件、处理动作、失败后的去向,以及由谁确认。判断标准很简单——如果另一个人拿着这份需求,遇到某条数据时能明确说出“走哪一步、停在哪里、交给谁”,例外描述才算合格。
不要从“我平时怎么维护博客”这种整体印象开始写需求。选一个已经处理过的页面,例如一篇分类整理稿,把当时的动作按顺序还原:打开哪个文件、看哪几个字段、满足什么条件才替换、替换后写回哪里。这个顺序就是脚本的正常流程。
正常流程只保留“全部条件都满足”的情况。比如:标题字段存在、分类字段非空、正文段落数量大于三,才执行批量补全。任何一条不满足,都不应该悄悄跳过,而应进入例外分支。这一步的产出是一张动作表,而不是一段说明文字。
实际动作:把样本页面的处理过程写成五到八步编号清单,每步注明输入字段和输出结果。做完这一步,你会立刻发现哪些判断依赖“看一眼就知道”,这些正是后面必须补写例外的位置。
人工经验里最容易被省略的是例外,因为人遇到异常会当场决定。脚本没有这种临场能力,所以每条例外至少写三段:
假设一个场景:脚本要为每篇文章补充分类标签,但某页正文里出现了两个互相矛盾的手写分类。此时触发条件是“同一页面候选分类数量大于一”,处理动作是“不写入,保留原标签”,失败去向是“输出到待确认清单,由人工选定后再重跑该页”。这只是说明写法的假设例子,不代表任何真实项目结果。
例外不是都要中断流程。写需求时要明确分两类,否则脚本要么过于激进,要么频繁停摆。
可以自动兜底的例外,通常满足两个条件:备用规则明确,且错误代价低。例如字段缺失时沿用上一版值,只要记录变更即可。必须停下来的例外,则是判断依据本身缺失或互相冲突,例如两个来源给出不同结论,而需求里没有规定优先级。
取舍依据可以这样比较:如果自动兜底后仍需人工逐条检查,那它并没有节省确认成本,反而增加了隐蔽错误;如果中断后人工只需做一次二选一,那中断就是合理的。把这两类分开写,脚本的例外分支数量会明显减少,也更容易验收。
需求写完不等于例外写全。选十到二十个页面做一次试跑,重点不是看正常流程跑通多少,而是看有多少页面落进了未预料的例外。每出现一条新例外,就回到需求里补写“条件—动作—去向”,而不是直接在脚本里加一句临时判断。
试跑结果会影响下一步:如果新例外集中在同一字段,说明该字段的正常规则定义过窄,应修改正常流程;如果新例外分散且各不相同,说明样本选得不够,应先扩大样本再改脚本。这里要注意,一次改动前后的对比不能只看处理数量变化,还要考虑内容季节性和需求波动,否则容易把无关变化当成脚本效果。
可执行动作:为试跑建立一张例外记录表,字段包括页面标识、触发条件、当时动作、最终去向。跑完一轮后,统计出现两次以上的例外,优先把它们写进正式需求。这样下一轮试跑的未知例外会减少,确认工作量也随之下降。
最后一步不是再读一遍需求,而是让不参与编写的人按需求处理三个刻意构造的异常页面:一个字段为空、一个字段冲突、一个目标位置被占用。如果对方能准确说出每页走哪条分支、停在哪里、交给谁,例外描述就达到了可执行标准。
若对方在某一页犹豫,说明该例外的触发条件或去向仍然模糊,应回到对应段落改写,而不是在口头补充。需求文档本身要能独立成立,这样后续换人维护或调整脚本时,例外规则才不会随人流失。