做报文设计这些年,我听惯了“业务又变了”“这个字段先加上以后用”“兼容一下吧”这类话。有一件事让我印象特别深:我们一套跑了四年的EDI订单报文,因为当初在枚举值里写死了“运输方式=1是公路”,当海外仓客户第一次传了空运单证时,整条链路从校验到制单全部报错,上下游五个系统围着这个字段改了整整一周。后来我翻出当年的设计文档,发现那个字段的注释赫然写着“取值范围暂定”。这四个字,就是所有矛盾的根源:你以为你写的是规范,其实写的是当下;你以为别人会按文档理解,其实别人只会按代码判断。
这份经验不是讲某套具体报文格式怎么写,而是讲一份EDI规范如何设计才能有至少三年的生命周期。适合正在制定企业间接口规范、供应链报文、金融单证或任何需要跨系统长期稳定传输的结构化数据的架构师和开发负责人。我把这些年做报文设计踩过的坑、总结出的原则,以及真正经得起时间检验的做法,一条一条拆开讲。
1. 规范的保质期,其实在你写下第一条segment时就定了
1.1 大多数EDI规范撑不过两年的真正原因:契约刚性对抗业务熵增
业务有个天然趋势:永远在变。今天是加一个门店编号,明天是拆一个计价单位,后天是给同一套订单增加“挂账”和“预支付”两种支付语义。每一条变化,最终都会落到报文字段上。
而EDI规范是契约。契约天生追求稳定,它要求双方按白纸黑字执行,不允许任何人临场发挥。稳定和变化这对矛盾,就是所有规范短命的根因。
我见过太多项目把规范设计成“数据库表结构的镜像”,直接把内部表的字段名、长度、是否可空照搬进报文。当时看起来没问题,可一旦业务侧调整表结构,报文就不得不跟着变,对接方也就被迫跟着升版、改解析、重测试。这不是做集成,这是给自己绑定时炸弹。
我在第一个项目里就犯了这个错误。 我们把订单表里的remark字段直接映射成报文里的remark,长度照抄200。结果业务部门把它当万能筐,什么都往里塞:结算备注、收货说明、发票抬头、甚至业务员内部叮嘱。半年后,凡是需要按备注做判断的逻辑全部不可靠,因为没有人知道里面现在装的是什么语义。
所以规范的保质期问题,本质上不是技术问题,是“契约刚性和业务熵增如何共存”的设计问题。三年不落伍的规范,靠的从来不是把所有未来都预测到,而是让自己“改得动”——每次业务变化都只动该动的部分,不牵连整份契约。
1.2 边界不清,才是规范最大的隐性成本
EDI报文跟写代码一样,最怕的不是逻辑复杂,而是职责不清。一份订单报文,头部信息、行项目信息、汇总信息、控制信息,必须各归其位。可实践中我见过太多规范,把所有不知道放哪儿的字段统统塞进一个“扩展块”里,美其名曰“为将来留空间”。
这种“统一扩展块”的问题在于:它没有语义边界。接收方拿到扩展块,不知道该按什么规则解析、校验、入库。久而久之,扩展块成了规范里的“灰色地带”,双方实现方式不一致,测试对不上,出了问题互相扯皮。
留白不是让一切空白,而是让每一块空白都有明确的职责。
我后来在制定规范时,每条segment和每个字段都明确标注三个问题:这条数据解决什么业务问题?它的数据来源是哪个业务实体?如果我不传这个字段,接收方应该怎么理解?这三个问题能过滤掉大部分“拍脑袋字段”。
1.3 三年不落伍的本质:让规范具备演化的能力
说白了,三年不落伍不是“三年不用改”,而是“三年内每次改动,都在可控范围内”。这就涉及到版本管理、扩展机制、校验策略三者的协同设计。后面几节我会逐一展开。
这里先记住一个核心观点:规范的演进能力,大于规范的内容完整性。 一份今天定义的再完善的规范,如果没有考虑明天怎么改,它就已经落伍了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 报文段层的“留白”:把责任边界钉死在定义里
2.1 头部、主体、尾部,各管一段,不要越界
凡是活得久的EDI规范,结构上几乎都遵守一个古老原则:头部放“关于这份报文”的信息,主体放“业务本身”的信息,尾部放“帮助接收方验证完整性”的信息。听起来像废话,但执行起来很多人就走样。
以订单报文为例:
- 头部(Header):报文类型、版本号、发送方、接收方、报文编号、生成时间、货币代码等。这些字段描述的是“这份报文是什么”,它们不该出现在行的层级。
- 主体(Body/Line):真正的业务数据。每个行项目自身的编号、物料、数量、单价、交货日期等。
- 尾部(Trailer):记录行项目总数、总重量、总金额等汇总信息,主要用来做完整性校验。
这个结构的好处是:当业务加了行项目种类(比如从“单品”扩展到“套装”),你只需要在主体部分新增一个段落结构,头部和尾部的解析逻辑完全不用动。这就是“段层留白”的实际意义:给每种变化预留一个独立的位置,而不是让它在整个报文结构里随机出现。
我早期设计过一份平面文件(Flat File)格式的报文,所有字段从第1个到第200个按固定位置排列,每个位置都必须有值。后来业务要在每个行项目上增加“原产地”和“批次号”,我不得不重新排版整个文件,把每个行项目后的所有字段全部后移。对接的公司整整排了一周的字段映射表。
从那以后我立了一个规矩:报文至少是两层结构(头加明细),凡是能分层的业务数据,绝不拍平。 这就是最朴素也最有效的“留白”。
2.2 段标识符的命名规则:命名空间就是编码空间的余量
在EDI领域,段标识符(Segment Tag)的传统做法是三位字母编码,比如EDIFACT里的UNH(报文头)、BGM(报文开始)、DTM(日期时间)、LIN(行项目)。这套体系能活几十年,除了它的标准化程度高之外,一个重要的原因是它的编码空间留足了余量。
这个思路可以迁移到任何自定义协议里:段标识符的命名规则,决定你未来扩展时改动的范围。
如果你用SEG001到SEG099这种连续序号来命名段,那么临时插入一个“分段”会非常痛苦——编号规则被打破,解析器的顺序判断逻辑也变得别扭。如果你用前缀表示段的职责,比如HD-*代表头部、LN-*代表行项目、TR-*代表尾部,每类再预留一批编号区间,未来的扩展就只是在各自区间内追加,不需要改动整体规则。
我的建议是:段标识符的第一层级必须是“类别”,第二层级才是“序号”。 类别决定了解析时的命运分派(路由到头部解析器还是行解析器),序号只负责段内的顺序。这样即便未来新增段,旧的解析器也能通过类别前缀正确判断新段是否需要自己处理,实现平滑忽略。
2.3 版本号放在头部第一段,这是全局设计的第一个决策
版本号的位置,我见过太多五花八门的做法——放文件名的后缀、放在报文体最末尾、放在业务主键后面。统一评价就一句:都不合适。
版本号必须放在接收方解析报文后最先看到的地方。 接收方读报文,第一步永远应该是“认版本”,然后才谈得上“按什么规则解析”。如果版本号藏在报文中间或者文件名的后缀里,接收方就不得不先假设一个默认版本,然后在整个报文中寻找版本标识,这个过程充满了歧义和异常分支。
EDIFACT的经典做法是报文头部第一段UNH里同时放报文类型和版本号,这是非常成熟的设计。你自己定制协议时,也请把version放在首条segment的固定位置,用固定长度或固定标签来承载。
这对“三年不落伍”的意义在哪里?一个规范能承受的最大风险就是版本更替,把版本号放在最显眼的位置,等于给所有历史版本都留了一扇门。 每次升级,旧解析器拿到新版报文,至少能在第一步就识别出“这不是我认识的版本”,从而正确地走拒收流程,而不是用错误的规则解析出荒谬的数据。
2.4 一个具体例子:实际项目中如何定义头段结构
我在一套供应链EDI项目里用的是自定义的XML报文,但设计原则沿用了EDIFACT的思路。头段的简化结构大致是这样:
xml复制<ORDER>
<HEADER>
<VER>2.1</VER>
<MSG_TYPE>ORDERS</MSG_TYPE>
<MSG_ID>202501150001</MSG_ID>
<SENDER_ID>SUP001</SENDER_ID>
<RECEIVER_ID>BUY001</RECEIVER_ID>
<SEND_TIME>2025-01-15T10:30:00+08:00</SEND_TIME>
</HEADER>
<LINE_LIST>
...
</LINE_LIST>
</ORDER>
注意几个细节:
VER独立成元素,不用属性,这样schema校验时可以对它单独做版本条件判断。SEND_TIME带了时区偏移量,这是做跨国报文时最容易踩的坑——两位对接方相隔几个时区,如果没有时区信息,任何一个日期字段都会被误解。- 头段和主体分离,
LINE_LIST是行项目的容器,未来如果出现多段不同类型的行项目(比如产品行和费用行),可以在这个容器下加子结构,头部完全不动。
这些细节都不是无聊的形式主义,它们决定了当某个节点发生变化时,你需要重写多少解析代码和测试用例。
3. 字段级别的“留白”:这是规范设计里最掏心窝子的部分
3.1 枚举值设计:永远不要钉死成业务常量
我在前面提到过那次“运输方式=1是公路”的事故。这里展开说说教训。
当时我们定义运输方式字段,文档里列了一张对照表:1=公路,2=铁路,3=海运。开发人员很自然地用switch把这三个值写死在代码里,后来的业务扩展就这么悲剧了。
问题的本质不是“对照表写错了”,而是我们把“运输方式”这个稳定的业务抽象和“当前支持的运输方式”这个变化的实例列表混为一谈。
正确的做法是:明确区分“稳定枚举”和“可变枚举”。
- 稳定枚举:比如性别(男/女/未知),这种枚举的业务含义几乎不会变,即使增加取值,也永远是在小集合里增加,影响面可控。这类可以放在报文规范里硬性定义。
- 可变枚举:比如运输方式、支付方式、仓库编码、渠道类型,这类取值的增长跟组织架构和合作方紧密相关,一定会变,而且变的频率远超你想象。这类枚举的正确管理方式不是写死在报文规范里,而是放进一个独立的码表管理系统,报文里传输的只是一个码值,码值的具体含义由收发文双方提前同步,而不是由报文schema唯一决定。
把这个原则落地到实际操作中,我在规范文档里会把字段分成两类:一类是“规范内定义”,一类是“码表引用”,后者的所有取值列表不在报文规范中维护,而是单独维护一份码表,附上版本号和更新日期。这样当新增一个运输方式时,只需要更新码表,报文的schema、解析器等都不需要变动。
这是我在EDI规范设计里最重要的一条经验,没有之一。
3.2 字段长度和精度:留出业务增长的空间
字段长度怎么定,能直观看出一个设计师有没有“留白”意识。
举几个真实的例子:
- 订单行号,一开始觉得单笔订单最多几十行,
NUMBER(4)够了。结果电商大促期间单笔订单能到几千行,直接溢出。 - 金额字段,一开始定
DECIMAL(10,2),后来业务扩展到日元,一张订单总额轻松破亿,还是溢出。 - 客户编码,一开始按“客户编号=6位数字”,等接了国外大客户,发现对方的客户编码是9位字母数字混合,字段直接没法用。
这些问题如果只是在内部数据库里还好说,ALTER TABLE一下就行;但在EDI报文里,字段长度一改,数据文件的结构就变了,对接方全部要跟着改,成本极高。
所以字段长度的定义逻辑,永远不能是“现在够用就行”,而是要考虑以下三个方面:
- 这个编号/代码系统未来的增长空间是什么?如果现在客户编码是6位,但你的客户规模每年增长20%,那么6位数字在几年内就会撞顶,直接给到12位甚至20位。
- 跨地域的文化差异。比如中文地址、俄文公司名,字段长度不能用英文字符的标准去估。
- 金额的小数位。币种不同,小数位就可能不同(比如科威特第纳尔是三位小数),再加上汇率换算、折扣分摊的舍入,稍有疏忽就会出现分厘级差异。
我个人的实践习惯是:编号类字段,至少在实际需求长度的基础上翻倍;金额类字段,整数位至少预留到业务峰值的十倍以上;所有字符串字段,在可预见的语义边界内尽量取整到2的幂(比如64、128、256),因为这会让接收方的缓冲区管理更高效。 这个习惯帮我躲过了好几次“再撑几个月就溢出”的尴尬。
3.3 必填、选填、条件必填:语法上的严格,语义上的宽容
初版规范最常见的问题,是把所有字段都设成必填,因为设计者觉得“既然定义了,就说明需要”。但现实往往是:某些字段只有在特定业务场景下才有值。
拿订单报文来说,“折扣率”这个字段,在普通零售订单里为空,在批发订单里就一定要有;“送达时间窗口”,在预约配送场景下必填,在其他场景下完全不传。如果你把所有字段都设成必填,接收方就只能收到一堆空值、零值、缺省值来“凑数”,而这些“凑数”的写法在不同系统中五花八门,反而制造出新的兼容问题。
我的经验是:把字段的“出现条件”和“取值规则”彻底分开定义。
- 出现条件描述的是“这个字段什么时候出现”,属于语法的范畴,应该尽可能清晰、机器可判定。
- 取值规则描述的是“出现之后,值要满足什么约束”,属于语义的范畴。
EDIFACT里有个成熟的概念叫“条件段”,意思是某些段是否出现取决于前面某个限定符的值。我们的自定义报文也可以如法炮制,比如:仅在payment_method=预付时,prepaid_amount才允许出现。
这样做最直接的好处是:接收方可以用schema级别的强校验,把“报文结构是否合法”和“业务数据是否合理”两个层面的问题分开报错。 结构错误说明是发送方的实现问题,可以亮红灯拒收;业务数据合理性问题则进业务流程去判断,不用一棍子打死。
3.4 “预留字段”的正确打开方式,以及它如何变成垃圾场
很多规范里都有“预留字段”,但绝大多数预留字段最后都变成了垃圾场——没有人规定它的语义,却人人都在用,最后谁都不敢删。
我在第一个项目里就让两个“预留字段”变成了垃圾场。一个叫attr1,一个叫attr2,当初只是为了“以防万一”加的。结果上线半年后,A系统往attr1里塞了“订单来源”,B系统往attr1里塞了“是否加急”,C系统往attr1里塞了“客户等级”。三个系统都拿这个字段做业务判断,但判断逻辑互不兼容,数据一交汇就乱了。
如果你真的想“留白”,预留字段的正确设计方式是:每个预留字段都必须具备明确的职责边界,而不是一个“通用垃圾桶”。
怎么给预留字段划定职责边界?我的做法是:
- 给预留字段命名时就要描述其可能的用途,例如
future_use_1改成reserved_for_region,future_use_2改成reserved_for_channel。 - 在规范文档里写清楚这个字段“不用于什么”。例如:“该字段为预留字段,当前版本禁止使用;任何业务需求不得将其作为通用备注字段。”
- 在schema校验里,对预留字段做限制:当前版本中该字段必须为空。这样即使有人想“临时用一下”,也会被校验直接拦下。
这套规则听起来保守,但正是这种保守,才能真正保护预留字段的价值。
3.5 空值、缺省、零值,三个完全不同的状态
这是接口开发里最容易产生歧义的一组概念。在EDI规范里,它们必须被严格区分:
- 空值(Empty):字段存在,但值为空。比如
<DISCOUNT_CODE/>,语义是“有意识的不提供”,可能是该场景下不适用,也可能发送方系统里确实没维护。 - 缺省(Absent):字段根本不存在。这在XML里表现为元素不出现,在位置文件里表现为字段被完全跳过。语义是“该字段与此次业务无关”。
- 零值(Zero):数值0。它是有明确业务含义的,比如“折扣金额为0”。
三种状态的差异,在业务上有决定性影响。比如金额字段,如果接收方收到一个空字符串,应该视为“未设置金额”而走异常流程,而不是当成“0元”;但如果发送方传的是缺省,可能意味着这个字段本来就不该出现在这个场景里。
所以字段定义时必须明确说明:“该字段为必填时,是否可以传空?是否允许缺省?零值是否和空值等同?”如果不定义清楚,双方联调时就会发现同样的报文被两个系统解析出完全不同的业务语义。
我建议在规范开篇加一节“通用数据规则”,把这几个状态的定义统一写好,后面每个字段引用它,而不是每个字段各写各的。 这能省去大量的沟通成本。
4. 版本与兼容策略:让规范长出一根“发展的时间轴”
4.1 主版本、次版本、修订版本的语义分配
三年生命周期里,规范一定会经历多次变更。变更不可怕,可怕的是每次变更都触发全链路升级。为了控制影响面,版本号本身要有语义,不能只是一个递进的数字。
我惯用三段式规则:
- 主版本号:发生破坏性变更时升级。比如删除字段、调整必填性、改变字段数据类型。这类变更要求所有参与方同步改造,通常伴随一个项目或一个发布窗口。
- 次版本号:发生兼容性变更时升级。比如新增可选字段、新增枚举值(前提是码表模式)、放宽长度限制。这类变更允许新老版本共存,老版本的报文仍能被新接收方正确处理。
- 修订号:无实质结构变化的修正。比如文档描述澄清、示例报文修正、校验逻辑Bug修复。
这个规则的价值在于:只要看到版本号的位次变化,接收方就能立刻判断自己“要不要动”以及“能不能无视”。 如果你的规范连版本号的三段语义都没有约定,那每次升版都是一次猜谜游戏。
4.2 向后兼容的判定标准,要能落到机器检查层面
“向后兼容”这个词经常被挂在嘴边,但实际执行时很多人靠感觉判断。我在项目里定义了一套相对硬性的判定标准,只要满足以下任意一条,就可以认为旧报文本版本不破坏兼容性:
- 新增了可选字段,且未改变任何既有字段的语义。
- 放松了某个字段的约束(例如允许的范围变大、长度变长)。
- 新增的码表值,但该字段的取值校验是“软校验”(接收方可以在业务层拒绝,而不是在解析层报错)。
反过来,只要出现以下任意一条,就必须升主版本:
- 删除了某个曾定义过的字段。
- 将必填改为选填,或选填改为必填(这会造成旧报文在新解析器下被拒收,或新报文在旧解析器下解析失败)。
- 修改了字段的数据类型、长度上限、枚举集合(在未采用码表模式时)。
这套标准要写进规范文档里,让每个参与者升版时按表自检,而不是开会讨论半天“你觉得算不算兼容”。
4.3 过渡窗口期设计:先双跑、再切换、后下线
版本切换最忌讳一步到位。我在做某一个企业间EDI升级时,定了一个“三周双跑期”的策略:
第一周:发送方同时生成本版报文和新版报文,但接收方只按本版解析,新版报文只做归档暂不处理。这周的目的是验证新报文的结构合法性和传输通路。
第二周:接收方开始按新版报文解析,同时继续接收本版报文,两套解析器并行。这个阶段最重要的任务是核对两套解析结果是否一致,一旦出现差异就要查根因。
第三周:所有参与方切换为新版报文,本版报文停止发送,但接收方仍保留本版解析器一段时间,用于处理历史在途报文。
这个策略的代价是多写一套生成或解析逻辑,但它能极大降低切换风险。尤其是跨公司的EDI对接,发送方和接收方不在同一个发布节奏里,双跑期可以吸收掉双方上线的时序差。
4.4 码表和枚举的中心化管理,是你手里最大的一张王牌
我在第3章说过,可变枚举应该独立成码表。这里把完整的运作方式讲透。
码表管理的最佳实践是建一个中心化的码表仓库(Registry),它至少包含:
- 码表的唯一标识和版本号。
- 每个码值的代码、名称、生效日期、失效日期。
- 每个码值的业务归属方联系人。
- 校验规则的机器可读描述(比如正则、允许值列表)。
发送方和接收方共同订阅这个仓库,报文规范本身不维护码表字典,只引用码表ID。这样做有三个直接收益:
- 新增码值不需要升级报文版本,只需要更新码表版本。
- 接收方遇到未识别的码值时,可以查码表仓库而不是打电话问对方。
- 码表有生命周期(生效/失效日期),过期码值在使用时会被标记出来,避免历史数据被语义误解。
如果你的项目还没有精力建立中心化码表,至少也要做到:把码表从规范文档中抽出来作为附件,并给附件单独编号维护。 每次更新附件不触发报文升版,跟处理规范正文的版本分离开。别小看这一步,它能救你于水火——凡是把枚举值直接写在报文规范正文里的,后来没有一个不后悔的。
5. 从“嘴上约定”到“机器可执行”:把留白变成约束
5.1 规范不能只靠文档,schema要有正确的校验粒度
文档写得再细,如果双方各自解析时的校验规则不一致,规范就是废纸。所以一份真正能落地的EDI规范,必须伴随一份机器可读的模型定义,在技术领域通常表现为XSD、JSON Schema,或EDI领域的EDIFACT DSD(Directory Schema Definition)。
但schema的校验粒度很有讲究。我的经验是:语法层面的校验要严,语义层面的校验要松。
- 严:范围是否合法、必填字段是否出现、日期时间格式是否正确、引用关系是否成立。这些属于语法,校验失败应当直接拒收。
- 松:这个业务值是否在码表里、这个金额是否符合业务预期。这些属于语义,应当放行到业务层处理,由业务规则去决定“能不能接受”,避免解析器因为语义判错一把抓。
把这两类校验混在一个schema里写,是很多项目的通病。一旦业务规则变了,schema就要改,解析器就要重发,整个链路都被绑死。正确做法是区分“结构校验Schema”和“业务规则配置”,前者跟着报文版本走,后者跟着码表和业务配置走。
5.2 拒收与错误码:让接收方在第一时间把问题说得清清楚楚
一个容易忽视但极影响体验的“留白”设计,是错误码机制。我记得有次对接方回传一个错误:“报文解析失败”。我们排查了整整一天,最后发现是日期字段少了一位。如果错误码能直接指出“第3个段,第2个字段,日期格式应该为YYYY-MM-DD”,这个排查就是秒钟级别。
所以规范里必须提前约定一个标准的错误响应报文结构,至少包含:
- 错误码(区分语法错误、语义错误、版本不兼容、无权限等)
- 出错位置(段标识+字段序号,或者XPath路径)
- 出错原因描述
- 接收方收到错误时的时间戳
这套机制和“留白”有什么关系?关系很大:错误码机制的本质,是给接收方一个标准化的“拒绝通道”。 没有标准拒绝通道的规范,接收方只能自由发挥,用日志、邮件、电话表达不满,那才是真正的混乱。
5.3 配套样例报文是规范的灵魂载体
我在评审别人的EDI规范时,第一件事就是看样例报文。一份没有样例的规范,再好的原则都只是空中楼阁。
规范文档至少要有三类样例:
- 最小样例:只包含必填部分,覆盖最简单、最标准的业务场景。
- 完整样例:包含所有可选部分,展示一份报文的极限形态。
- 异常样例:故意做一份非法报文,配合错误码文档展示拒收流程。
这三类样例各自解决的问题不一样:最小样例帮新手快速打通链路,完整样例帮开发理解所有字段,异常样例帮双方联调错误处理逻辑。我见过不少项目把这三者混在一起——只有一份完整的“真实报文”,结果新手想对照着写一个最简单的报文,得从几百行里挑出要用的字段,效率极低。
5.4 规范文档和评审流程:把“留白”精神沉淀成团队共识
最后说一个偏“软”的层面:规范文档本身怎么写、评审会怎么开。
我见过最高效的规范文档,不是那种几百页全是字段定义的大部头,而是金字塔结构:
- 第一层:设计原则和总体架构,不超过10页,讲清楚为什么这样设计。
- 第二层:通用规则和版本策略,5-10页,讲清楚所有段和字段的公共约束。
- 第三层:分模块的字段定义,这部分可以很厚,但每个字段的表格式描述要简洁一致:名称、标识、类型、长度、必填性、出现条件、取值规则、示例、备注。
评审会不要只评“字段全不全”,重点应该放在“未来三年这个字段可能怎么变”,以及“如果这个字段变了,哪些地方要跟着改”。把这些讨论沉淀在文档的“设计记录”小节里,这份规范才是活的。一份有设计记录的规范,十年后还能看得出当时为什么这样留白;一份没有设计记录的规范,三年后连作者自己都说不清当初的想法。
6. 回望这几年实战,我最后悔和最后悔没做的事
如果让我给准备做EDI规范的人一句总结,我会说:设计报文规范,本质是在设计一套“变化时的成本分布”。 你越愿意在设计阶段多花一点心思去留白,未来的每一次业务变化就越从容;你越想在当下省事,未来每一次变化就都会变成一场事故。
回头看我做过的项目,最后悔的事情就是早期把枚举值直接写死在报文里,没有认识到“业务常量”和“业务抽象”的区别。当时省掉的那点规范管理成本,最后用几倍的联调工时还了回去。而最后悔没做的事,是没有从一开始就建立中心化码表仓库。当时觉得项目体量小,一个Excel够用了,等接的合作伙伴多了,码表分散在各份邮件和Excel附件里,版本对不上,找人问来问去,那时候才意识到这个账迟早要还。
如果你正在制定或重构一份EDI规范,我的建议是从今天开始做三件事:
- 在任何字段上写死任何枚举值之前,先问一句:这个取值列表,明年还会是这个集合吗?
- 给每一种预留的扩展点,都配上至少一句话的职责说明,并在schema里加上限制,宁缺毋滥。
- 把版本号放到报文头部最显眼的位置,并把兼容性判定标准写进规范正文,让所有人都能照着检查。
最后再分享一个我最近一直在用的小技巧:给规范里的每个字段增加一条“变更历史”的迷你段落,不用写复杂,就记录“这个字段在哪个版本里因为什么需求调整过”。一开始大家都嫌烦,但坚持三个版本之后,这套历史记录成了团队内部最有价值的资料,很多“当时为什么要这样设计”的问题,翻一下历史记录就豁然开朗了。这就是留白的另一层意义——它在帮未来的你,留下理解现在的自己的余地。
