直接回答:例外情况不能只写“特殊情况另行处理”,而要写成可判定的触发条件、脚本动作和交回人工的出口。把人工经验转成脚本需求时,真正难的不是正常流程,而是那些人工会凭经验绕开的边界。描述例外时,先区分“可以自动兜底”和“必须停下来问人”两类,再给每类写清楚判据、动作和记录方式。
常见现象是:需求文档把例外列得很多,脚本上线后却频繁误判;反过来,例外写得很粗,脚本遇到边界就静默跳过,人工又得回头补。两种结果都让人怀疑“是不是不该把例外写进脚本”。
这里有两条看似都合理的路。第一条是穷举例外:把人工遇到过的所有边界都写成规则,认为覆盖越全越稳。第二条是只写主干:例外交给人工判断,脚本只处理标准情况,认为这样更灵活。两条路都成立,但成立条件不同。
穷举例外适合边界稳定、判据可量化、误判代价低的环节,比如字段缺失、格式不符、数值超出预设区间。只写主干适合边界高度依赖语境、判据难以量化、误判代价高的环节,比如内容是否触及敏感表述、某条经验是否适用于新对象。选错方向的代价是:穷举会把维护成本推高,只写主干会让脚本在关键边界上悄悄放过问题。
要判断某个例外该写进脚本还是交回人工,可以收集三类证据。
一个假设例子:某团队把“页面标题与正文主题不一致”作为例外。若他们能定义“标题关键词未出现在正文前两段且正文长度低于某阈值”这一条件,误判只触发提醒,就可以先写成脚本告警;若该判断会直接改写标题,则应先交人工确认。这个例子的数字只是说明比较方法,不代表实际阈值。
每条例外至少包含四部分:触发条件、脚本动作、人工出口、记录字段。触发条件要写成可判定的表达式,避免“异常”“不合适”这类无法执行的词。脚本动作要明确是跳过、标记、降级还是暂停。人工出口要说明在什么情况下必须交回人,以及交回时携带哪些上下文。记录字段要能支持事后核对,比如输入标识、命中规则、处理结果、时间。
实际动作示例:先挑一条人工最常绕开的例外,按上述四部分写成需求,只让它产生标记而不改动数据。运行一段时间后,检查标记是否集中在少数可解释的原因上。若标记大量来自同一类可判定条件,下一步可以把该类从“标记”升级为“自动兜底”;若标记分散且互相矛盾,说明判据还不稳定,应继续保留人工出口。这个动作的结果直接影响下一步是扩大自动化范围,还是先补充判据。
面对“写细”还是“写粗”,可以按顺序问三个问题。
三个问题都指向自动化时,才适合把例外写成脚本规则;只要有一个指向人工,就应把该例外设计成“停下并交回”。代价是:自动化程度低会增加人工负担,但能避免脚本在关键边界上做出难以撤回的处理。反过来,自动化程度高能减少重复劳动,但需要持续维护判据,并接受误判后修正的成本。
比较例外处理改动前后的效果时,不能只看标记数量或处理速度的变化。搜索需求本身会随季节和事件波动,数据采集口径也可能因字段调整而变化。一次改动前后标记减少,可能是判据放宽导致漏报,也可能是真实例外减少。要区分这些解释,应固定采集口径,保留改动前后的原始记录,并抽查被标记和未被标记的样本,确认处理结果是否符合预期。请求量、抓取量或某项统计归零,同样不能单独证明处理正确,还需要检查是否有其他环节改变了输入或过滤条件。
把例外写成脚本需求,核心不是追求一次写全,而是让每条例外都有明确的触发、动作和交回路径。先让例外可见、可核对,再决定哪些可以自动兜底,哪些必须留给人判断,这样脚本才不会在边界上替人做它做不了的判断。