直接回答:不要只写“正常情况怎么处理”,而要把例外写成可判定的条件分支——给出触发条件、判定依据、处理动作和回退路径。判断标准是:执行脚本的人或程序,能否在遇到边界样本时做出与你人工处理时相同的决定。若不能,说明例外描述还不够具体。
假设你运营一个内容站,长期靠广告和联盟链接变现。你的人工经验是:文章正文超过一定长度、且读者停留较久时,在第二段后插入广告位效果较好。你打算把这条经验写进脚本,让程序自动决定广告位插入位置。第一版需求很可能写成“正文超过800字就在第二段后插入广告位”。
这个写法在少数样本上成立,但规模化后会出问题:有的文章第二段是列表或引用,插入后破坏阅读;有的文章本身是短讯,字数达标但结构不适合;有的页面已有联盟链接,再插广告会互相抢注意力。这些就是例外,必须在需求里单独描述,而不是留给执行者临场判断。
把每条例外写成四段式,能显著减少歧义。以“第二段是列表”为例:
<ul> 或 <ol>。这四段缺一不可。只写“遇到列表要小心”,执行者不知道是跳过、改写还是放弃;只写“跳过”,又不知道跳到哪里、跳几次算失败。
并非所有例外都能写成脚本。判断方法是问:这个例外能否用页面自身的数据或结构稳定识别?
把第二类硬写成规则,往往产生大量误判。更稳妥的做法是缩小自动处理范围,把不确定的部分交还给人工,而不是追求全自动。
人工经验来自个别样本,规模化后失效,通常是因为样本的隐含前提没有被写出来。回到前面的假设情境,人工挑选广告位时其实默认了三个前提:文章是叙事型长文、正文没有其他商业元素、读者以自然流量为主。脚本若照搬“字数达标就插入”,等于丢掉了这三个前提。
因此需求里应显式写出边界:
写出边界后,脚本的适用范围变小了,但误判率下降,人工复核量也随之减少。这是取舍:覆盖率换稳定性。若你更看重覆盖,可以放宽边界,但必须同步增加复核环节,而不是假设放宽后不会出问题。
需求写完后,不要直接全量上线。先取一批结构差异明显的页面试跑,重点看两件事:命中例外的比例,以及回退路径是否被真正执行。假设试跑发现大量页面因“已存在联盟链接”而跳过,说明这条边界可能过严,需要重新判断它是否真的必要。
比较改动前后效果时要注意:搜索需求本身会随季节波动,数据采集口径也可能不同。因此不要用一次前后对比就断定规则有效,而应看例外处理是否符合预期、人工复核量是否下降。若例外频繁触发且原因集中,说明需求描述还缺一类条件,应回到四段式结构补充,而不是直接调参。
把例外写清楚的实际结果,是让脚本在边界处停下来或绕开,而不是硬套规则。下一步动作取决于试跑中例外触发的分布:集中在一类原因就补条件,分散且语义相关就转为人工队列。