结论先给:如果对象格式变化只是字段顺序、分隔符或大小写这类表层差异,优先在输入前做规范化转换,不要动原有校验规则;如果变化涉及对象类型本身,比如从单条URL变成URL前缀、从页面变成站点目录,则必须改校验规则,否则后续所有判断都会建立在错误前提上。判断依据是:变化后的对象是否还能用同一套规则唯一识别。不能唯一识别时,继续沿用旧规范只会让错误数据混入,代价是后续排查方向被带偏。
表层差异的典型表现是同一对象换了写法。比如原来输入完整URL,现在只给路径;原来用逗号分隔,现在用换行分隔。这类变化不改变对象的身份,只改变表达形式。处理方式是在读取阶段统一转换,输出仍走原来的校验逻辑。
类型差异则不同。原来提交的是单个页面,现在提交的是带通配符的目录规则;原来核对的是域名,现在核对的是子域或协议变体。此时对象的边界变了,旧规则可能把合法对象判为非法,也可能把不该纳入的对象放进来。这两种误判的代价不一样:前者会漏掉真实对象,后者会污染后续统计和判断。
一个可操作的区分方法是:把变化前后的对象各自写成最小可识别单元,看两者能否互相推导。能推导,按表层差异处理;不能推导,按类型差异处理。
保留旧规范并加一层转换,适合以下条件同时成立:对象类型未变;变化只出现在输入侧;转换规则可以写成确定性步骤;转换后的结果与旧规范下的结果可逐条对应。
重建规范适合另一种情况:对象类型已经改变,或者转换规则依赖人工判断、无法稳定复现。此时继续用旧规范加转换,短期看似省事,长期会让规则里堆积大量例外分支,维护成本高于直接重写。
两种做法的代价可以这样比较。保留旧规范加转换,代价是转换层可能隐藏错误,一旦转换逻辑有偏差,问题会出现在下游而不是入口。重建规范,代价是需要重新验证一批历史对象,短期内无法直接沿用旧结论。选择时看哪个代价更可承受:如果下游判断依赖精确对应关系,优先重建;如果只是做粗筛,转换层更划算。
假设原来输入规范要求填写站点内的路径,例如 /a/b,现在上游改为提供完整URL,例如 https://example.com/a/b。表层看只是多了协议和域名,但校验规则若仍按路径匹配,完整URL会因为开头不是斜杠而被判为非法。
处理动作:在读取后先剥离协议和域名,只保留路径部分,再送入原有校验。这个动作的结果是,旧规则不需要改,但需要新增一条断言,确认剥离后的路径以斜杠开头。如果剥离失败或结果为空,就不能静默跳过,而应记录为待人工确认的对象。下一步取决于这条断言的通过率:通过率稳定,说明转换可靠,可以继续沿用旧规范;断言频繁失败,说明上游格式并不统一,此时应改为重建规范,明确要求上游提供统一格式,而不是在下游不断补转换分支。
前面结论有一个反例:当格式变化只是表象,但上游同时改变了对象的取值范围时,按表层差异处理就会失效。比如输入仍是一条URL,但上游从只给已发布页面,变成同时给草稿、重定向和参数变体。此时格式没变,对象集合变了。
这种情况下,剥离或转换都无法解决问题,因为真正变化的是纳入范围。正确动作是先明确哪些对象应当被纳入校验,再决定规则。若继续沿用旧规范,会把草稿和重定向当作正式页面处理,导致后续判断基于不该出现的对象。
区分方法:对比变化前后同一批对象的数量与构成。数量变化本身不能单独说明问题,因为采集范围、去重方式或上游过滤条件变化也会造成同样现象。需要看构成,比如是否新增了带参数的变体、是否出现了非正式状态的对象。只有构成变化指向取值范围改变时,才需要重建规范。
先抽取一小批变化后的对象,按最小可识别单元分类,统计其中有多少能通过旧规则、多少不能。对不能通过的对象,逐条记录失败原因,判断是表达形式问题还是对象边界问题。如果失败原因集中在表达形式,增加转换层并重新验证;如果失败原因分散在对象边界,停止修补旧规则,改为重建输入规范并重新验证历史对象。验证通过前,不要用这批数据得出任何结论。