☰
对外接口设计规范:三条原则与十六个检查点
2026/11/3 20:30:27 网站建设 项目流程

接口这东西,写的时候是自己爽,用的时候是别人疼。我见过太多团队,对内接口随手一写,反正调用方就坐在隔壁工位,出问题喊一嗓子就改;可一旦这个接口要对外,性质就完全变了——对面可能是合作方的三个开发、两套技术栈、一个排期满到没空陪你联调的负责人。去年冬天就遇到过这么一档子事:某业务方的对接同学在群里甩了张报错截图,配文“你们这个接口上周还能调通,今天全挂了,我们上线卡这儿了”,我翻了自己这边的日志,发现只是给某个响应字段换了个类型,从字符串改成了数字,内部自测全绿,对外直接炸了。这件事之后我把对外接口的规矩重新捋了一遍,归结成三条原则、十六个小点,此后每次评审新接口都拿这张单子过一遍。这篇就把这套东西完整摊开讲,包括每个点为什么这么定、实际怎么落地、以及那些只有真被对接方骂过才会记住的细节,适合正在设计开放接口、合作方接口、平台能力输出的同学参考。

1. 先把“对外”两个字掰开来看

1.1 对内接口靠嘴沟通,对外接口只能靠契约

内部接口和对外接口最大的差别,不在技术难度,而在信息传递方式。内部接口的隐含信息可以靠口头传递:这个字段可能为空、这个枚举只有三种值、这个接口调用完三秒后才会真正生效——这些话在需求评审会上说一遍,调用方记住了,接口就能跑。但这套逻辑在对外场景下彻底失效,因为对接方看不到你的代码,问不到你的值班同学,甚至可能在你改完接口之后的第三周才开始联调。

所以对外接口的本质是一份单方面履约的合同:你承诺输入什么、输出什么、异常怎么表现、什么时候会变,对方基于这份合同写代码。合同里没写的东西,对方就有理由认为不会发生;合同里写了的,你就得兜住。我后来给自己定了个判断标准——如果一段接口说明需要配一次电话会议才能讲清楚,那它就不合格。这个标准听起来苛刻,但它能帮你砍掉大量“我们内部知道就行”的侥幸心理。

还有一个常被忽略的点:对外接口的调用方数量是发散的。内部接口通常就三五个调用点,改一次全改完;对外接口一旦发布,调用方数量你根本控制不了,可能明天就有人拿它接进生产系统。这意味着任何一次非兼容变更,成本都不再由你决定。理解了这一点,后面十六条小点里有一大半其实就是从这句话推导出来的。

1.2 三条原则是怎么来的:把对接方的抱怨翻译成设计约束

这三条原则不是我拍脑袋想的,是从历次对接事故的抱怨里反推出来的。我把近两年收到的典型反馈归了个类,发现抱怨基本落在三个方向:第一类叫“说好的事你变了”,比如字段类型改了、错误码语义换了、返回结构加了一层;第二类叫“我得猜”,比如分页参数每个接口都不一样、时间格式有的带时区有的不带、某个字段到底必不必填文档里没写;第三类叫“出事了找不到人”,比如报错了但没有任何请求标识、日志里查不到这次调用、接口挂了没有降级方案只能干等。

对应下来就是三条原则:

原则要解决的问题通俗说法
契约先于实现承诺不清晰、随意变更说到做到
把复杂度留给自己对方要猜、要适配、要写特判少让人动脑
为变化和故障留位置出事了无从下手、升级时无路可退提前挖好沟

这三条原则的价值在于,它们不是空话,每一条都能拆成可检查的条目。下面我按原则分组,把十六个点逐个讲清楚,每个点都会说明为什么这么定、实际怎么写,以及不这么写会踩什么坑。这些点是给评审用的,不是给背诵用的,能对上号比记住编号重要得多。

2. 原则一:契约先于实现,让接口说到做到

2.1 命名要能自解释,别把缩写当个性

第一个点看起来最基础,但它是返工率最高的一项。我见过叫/api/v1/doIt的接口,也见过叫queryDataListInfo的路径,还见过参数名叫tp、st、flag的。写的人当时心里清楚,三个月后自己都得翻代码。对外接口的命名有一条硬标准:不看文档,仅凭路径和字段名能猜出七八成语义。

具体做法上,路径用“资源 + 动作”的结构,名词用复数,动作优先用 HTTP 语义表达,实在表达不了再在路径里加动词。比如查询某订单下的明细,GET /v1/orders/{orderId}/items比POST /v1/getOrderItem清楚得多。字段名统一用一种命名风格,要么全下划线要么全驼峰,别在一个响应体里混着来——这个细节在跨语言对接时特别要命,有的序列化框架对混合风格的兼容性很差,对接方得为每个字段写单独的映射。

还有一类隐性问题:缩写歧义。amt是金额还是数量?no是编号还是布尔否?cnt是计数还是内容?我的建议是,凡是长度在四个字母以内的缩写,除行业内绝对通用的(如id、url),一律展开写全。多打几个字母的成本,远低于一次“这个字段到底啥意思”的沟通。命名这件事没有技术含量,但它决定了对接方第一眼的心理预期,第一眼就懵的接口,后面很难建立信任。

2.2 入参校验沉到最外层,别让脏数据穿透业务

第二个点是我认为最容易被内部思维带偏的。内部接口经常图省事,参数直接扔进业务逻辑,靠下游某处兜底;但对外接口必须在最外层做完整校验,把非法输入挡在业务之外。原因很实际:对外调用的参数不可信,对接方可能传空、传超长、传负数、传一万条、传昨天的时间戳,你没法假设对方会按文档来。

落地时的分层顺序是这样的:网关层做协议级校验(大小、格式、必填),应用层做业务级校验(状态是否允许、额度是否够、对象是否存在),业务层只处理已经合法的数据。这样分层的好处是错误定位清晰——格式错就返回参数错误,业务不满足就返回业务错误,不会出现“参数格式没问题但下游报空指针”这种两头说不清的状况。

校验的具体规则要写成可执行的约束,不是“长度合理”“时间有效”这种描述。比如字符串长度写 1 到 64,数字写区间,枚举写全量取值,日期写清是否允许未来时间,数组写最大元素数。我在实际项目里会把这份约束直接落到接口定义的 schema 里,让框架自动生成校验代码和文档,避免文档和实现两张皮。这一点后面第 4 章还会展开讲,因为校验约束一旦和实现脱节,就是最典型的“文档骗人”事故。

提示:校验失败时不要只返回“参数错误”四个字,要明确指出哪个字段、违反了哪条规则、期望什么格式。这一条能省掉对接方一半的沟通成本。

2.3 响应包体统一,让对接方只写一次解析代码

第三个点是关于响应结构的。很多接口的响应体长这样:查询成功返回一个数组,查询失败返回{"msg": "xxx"},参数错误返回{"error": "yyy"},甚至还有直接返回纯文本的。对接方每接一个接口就得写一套解析逻辑,加一个接口改一次代码,这种设计在对接方那边的口碑基本不用想。

标准做法是全站统一响应包体,固定几个顶层字段:业务状态标识、提示信息、业务数据、请求追踪号。所有接口,无论成功失败,结构完全一致,成功时数据区有值,失败时数据区为空,异常情况下 HTTP 状态码和业务状态标识各自表达各自的意思。这样对接方的解析代码可以做成通用拦截器,一次写好,全站复用。

这里有个争议点值得说清楚:HTTP 状态码和业务状态码要不要都用。我的做法是两个都用,但职责分开。HTTP 状态码表达传输与协议层面的结果(成功、未认证、无权限、不存在、限流、服务错误),业务状态码表达业务逻辑的结果(额度不足、状态不允许、重复提交)。好处是中间层设备、监控系统、网关规则可以直接基于 HTTP 码做处理,不用解析包体;而业务上的细分原因由业务码承担。两套码混用的反面案例是把业务失败也返回 HTTP 200,然后所有监控都看不到异常,接口天天报错但大盘一片绿,这个坑我踩过一次,排查了整整一个下午才发现监控根本没在统计错误率。

2.4 错误码分层编号,可检索可定位

第四个点接上一条往下走。统一了错误码字段,还得管错误码本身怎么定。最差的情况是错误码满天飞,几百个数字,没有规律,文档里一搜一个准但没人记得住。我的做法是分层编号:高位段表示错误大类,中间位表示子模块,低位表示具体错误。

举个例子,六位码10 03 01大致可以理解为“参数类 / 订单模块 / 订单号格式非法”。这样设计之后,对接方看到一个错误码,即使不查文档也能大致判断是自己的问题还是对方的问题,排查方向立刻清晰。同时每一类错误码的数量要控制住,一个模块超过二十个具体码就该考虑合并了,码太多实际上等于没有码。

除了编号,还有两件事必须做:一是错误码必须有唯一对应的文案,同一个码不能在不同场景下给出不同解释;二是错误码的语义一旦发布就不能改,如果需要新的含义,加新码而不是改老码的释义。这条约束看似保守,实际上是在保护对接方的历史代码。我见过一次把“余额不足”的码复用到“优惠券不可用”上,结果对接方的重试逻辑被触发,白白多扣了一笔,这种事在对外场景下是事故级别的。

2.5 幂等键显式声明,重试才敢放心

第五个点是关于重复请求的。任何走网络的调用都会遇到超时,超时之后调用方的自然反应是重试,而重试意味着同一个业务请求可能到达两次以上。如果接口不幂等,第二次请求就会重复扣款、重复建单、重复发券。这个问题的根源不在调用方,在接口设计——接口必须显式告诉对方:这个接口幂等吗?如果不幂等,重试要带什么标识?

具体做法是,对会产生副作用的写接口,要求调用方在请求头或参数里带一个业务唯一的幂等键,服务端用这个键做去重,同一键的重复请求直接返回首次的结果,不重复执行。幂等键的生成规则要写清楚,通常建议用业务单据号加操作类型的组合,长度和字符集也要约定,避免对方传了超长键导致存储问题。

这里有个容易忽略的细节:幂等结果的保留期。去重记录不可能永久保存,得约定一个窗口,比如二十四小时,超过窗口的重复请求可能会被重新执行。这个窗口必须写进文档,因为调用方的重试策略可能跨越很长时间(比如定时补偿任务隔几小时跑一次)。另外,查询类接口天然幂等,不用特殊处理,但要在文档里明确标注,这个标注能让对接方放心做本地缓存和重试,这个收益比想象中大。

2.6 版本走路径,兼容只增不改

第六个点是版本管理,它直接决定你后面还能不能安全地演进。我采用的策略很朴素:版本号放在路径里,比如/v1/、/v2/,同时坚持一条铁律——同一个版本内,只允许新增,不允许修改和删除。

“只增不改”具体指什么?响应里可以加新字段,不能改已有字段的类型和语义;请求里可以加新的可选参数,不能把可选改成必填,也不能改参数格式;错误码可以加新的,不能改老码的含义。这套规则听起来束手束脚,但它换来的是一份稳定的承诺:对接方基于 v1 写的代码,只要 v1 还在,就不会因为你的日常迭代而崩掉。

版本升级的时机也要有节制。我见过每改个小需求就升一个大版本的团队,结果 v1 到 v9 同时在线,维护成本爆炸。比较合理的节奏是,只有当破坏性变更积累到一定量、或者业务模式发生结构性调整时才开新版本,日常迭代靠新增字段解决。老版本的退役必须走公告流程,这一点放在第 4 章最后一节细说,因为它是整个生命周期里最容易被跳过、也最容易引发事故的环节。

3. 原则二:把复杂度留给自己,把确定性交给对方

3.1 分页排序过滤三件套,一套规约用到所有列表

第七个点是关于列表类接口的。一个系统里通常有十几个列表接口,如果每个接口的分页参数各写各的——有的叫page有的叫pageNum,有的从 0 开始有的从 1 开始,有的每页上限 100 有的上限 20——对接方就得为每个接口写一套适配。这种成本是纯浪费,而且极易出错,尤其是页码起始值差 1 这种问题,测试不覆盖根本发现不了。

我的做法是全站统一一套规约:页码从 1 开始,每页数量参数统一命名,默认值和上限固定,排序参数用“字段名 + 方向”的固定格式,过滤参数用明确的字段前缀区分。响应里除了数据列表,固定返回总数、当前页、每页数量三样,让对接方能直接算总页数做分页器。

还有个细节:总数要不要每次精确统计。数据量大的表做精确计数很慢,有些团队会改成近似值或者干脆不返回。如果确实做不到精确,必须在文档里写明这是估算值、误差范围大概多少,不要含糊地返回一个数字让对接方拿去显示“共 XX 条”。我见过对接方拿估算值做分页渲染,用户翻到最后一页发现是空的,反馈到我们这边说是“数据丢失”。技术上的取舍没问题,问题在于取舍的信息没有传递给使用方。

3.2 时间、金额、枚举:单位和格式必须写死

第八个点是格式化约定,这类问题属于“不讲清楚必然出事”的典型。时间戳用秒还是毫秒?字符串时间带不带时区?金额用元还是分?浮点还是字符串?枚举传数字还是字符串?这四个问题每一个都有过血案。

我的固定做法是:时间统一用带时区的标准格式字符串或者毫秒时间戳,二选一并全站一致,绝不混用;金额统一用最小货币单位的整数或高精度字符串,禁止用浮点数,因为浮点数在跨语言序列化时会出现精度丢失,一分钱的差异在对账时能查一整天;枚举统一传字符串常量而不是数字,数字枚举一旦有人调整顺序就全乱,字符串虽然长一点但可读性和稳定性都更好。

这些约定要写进一份全局约定文档,而不是分散在各个接口的说明里。全局约定文档的好处是新接口自动继承,对接方只需要读一次。我在实际项目里会把这几个格式约束做成公共的类型定义,让接口定义直接引用,这样从机制上保证不会有人写出个“金额用浮点”的新接口。约定这种东西,靠自觉不如靠工具,工具拦得住,人才不会犯错。

3.3 必填可选、长度边界,都写进契约里

第九个点是契约的颗粒度。很多接口文档只写了字段名和类型,没写必填与否、没写长度范围、没写取值范围。对接方只能靠试:传了看报不报错,报错了再猜原因。这种体验极差,而且会把你的服务当成试验田,日志里全是无效请求。

合格的字段说明应该包含:名称、类型、是否必填、长度或数值范围、取值枚举、业务含义、示例值。六项齐全,对接方基本不需要问问题。其中“是否必填”和“边界”这两项最容易被省略,也最容易出问题。必填项不写清楚,对接方漏传,你返回参数错误,对方觉得你文档没写;边界不写清楚,对接方传了个刚好超长的值,线上直接报错。

对于可选项,还要额外说明不传时的默认行为。比如分页大小不传默认多少、排序不传默认按什么排、时间范围不传默认查多久。默认行为是契约的一部分,写清楚了对接方才能预判结果。我遇到过对接方不传时间范围,结果默认只查最近七天,对方以为是全量数据,做出来的报表数字对不上,来回扯了两天。

3.4 批量接口给上限,单条接口给限流

第十个点是容量约定。对外接口必须明确告诉对方:一次最多能传多少条、一秒最多能调多少次、超了会怎样。这三个数字如果不写,对接方要么保守地一条条调(性能差,还怪你接口慢),要么一次性传十万条(把你的服务打挂)。

批量接口的上限要基于你实际的承载能力来定,并且留出余量。比如单次批量最多一百条,单条请求体最大一兆,这些都要在文档里写明,同时在服务端做硬校验,超了直接返回参数错误并说明上限值。限流则要在网关层做,超出配额返回明确的限流错误码,并且建议带上建议重试的时间。

这里有个实操经验:限流阈值不要设置成刚好等于宣传值。宣传“每秒一百次”,实际阈值可以设成一百二,给突发流量一点缓冲,避免对接方的正常波动就被拒。同时要在响应头里返回剩余配额,让对接方能自己控制节奏。这件事做了之后,限流相关的投诉会下降一大截,因为对方能看见自己快超了,会主动降速,而不是被突然拒绝后一头雾水。

3.5 异步通知要有重试、要有去重、要有签名

第十一个点是异步场景。只要有回调、有消息推送,就必须回答四个问题:推失败怎么办、重复推怎么办、对方怎么确认收到、怎么防止伪造。这四个问题少答一个,异步链路就是不可靠的。

我的标准配置是:失败按指数退避重试若干次,每次间隔递增,超过次数后进入死信并告警;每条通知带唯一消息标识,供对方去重;对方返回明确的成功标识才算送达,其他情况一律视为失败继续重试;通知内容带签名,签名覆盖时间戳和业务字段,防篡改也防重放。

重试策略的细节值得多讲一句。重试间隔不能太短,短了会把对方的故障期打穿;也不能太长,长了数据延迟太大。我一般用几十秒起步、逐次翻倍、总时长控制在数小时量级,同时提供手动重推的入口,用于对方修好之后的补推。另外,重试必须限定在可重试的错误上,对方明确返回“业务拒绝”时不该重试,否则会一直推一条对方永远不接受的数据,日志里刷满无用记录。

4. 原则三:为变化和出事提前留位置

4.1 预留扩展字段,但别把预留当垃圾桶

第十二个点是关于扩展性的。业务一定会变,接口一定会加字段,提前在响应体里留一个扩展区是常见做法。但预留这件事很容易走偏,变成什么乱七八糟的东西都往里塞,最后扩展区成了一个没有契约的垃圾场,对接方根本不敢用。

我的用法是给扩展区定三条规矩:一是扩展区内的字段必须也在文档里登记,不能因为是扩展区就不写;二是扩展区不承载主流程必需的字段,主流程该有的字段必须在顶层明确定义;三是扩展区的字段同样受“只增不改”约束。这样扩展区就是个有秩序的缓冲区,而不是法外之地。

另一种更克制的做法是不留扩展区,需要加字段时直接在响应体顶层加新字段。因为 JSON 这类格式本身对未知字段是宽容的,老版本对接方解析时会自动忽略不认识的字段,所以加字段本身就是向后兼容的。这种做法更简单,前提是你确信对接方用的解析器不会因为未知字段报错——这一点在文档里提醒一句即可。我个人更倾向后者,扩展区在实践中的使用率其实很低,维护成本反而更高。

4.2 全链路 requestId,出问题能一条线拉到底

第十三个点是我认为性价比最高的一个。每个请求进来生成一个唯一标识,贯穿网关、应用、下游服务、日志、响应头,全链路带着走。对接方报问题的时候,只要把这个标识给你,你就能在日志系统里一把捞出这次调用的完整链路,不用再问“你几点调的、调的哪个接口、参数是什么”。

这个机制的实现成本很低,一个过滤器加一个日志字段就够,但它带来的排查效率提升是数量级的。我在没有这个机制之前排查问题,平均要和对接方来回三四轮才能锁定是哪个请求;有了之后基本一轮搞定。所以我在任何对外接口的设计评审上,只要看到没有请求标识,直接打回。

要发挥效果,还有两个配套动作:一是响应头里必须回传这个标识,不然对接方拿不到;二是错误响应体里也要带上,因为对接方最容易在报错时截图,截图里有标识就能直接查。有些团队只在成功响应里带,报错时不带,等于把最有用的场景漏掉了。这个细节我在文档模板里固化下来了,新接口上线自动带,不用每次提醒。

4.3 文档里的示例要能直接跑

第十四个点关于文档质量。判断一份接口文档合不合格,我有个简单办法:拿文档里的示例请求,原样复制到工具里发一次,看返回是不是和示例响应一致。如果跑不通,文档就不合格。这个标准很朴素,但能满足的团队并不多。

常见问题是示例是手写的、和实际不符,或者示例里的字段值是理想值,真实场景下根本不会有。更隐蔽的问题是示例没有覆盖异常情况,对接方只看到成功的样子,不知道失败长什么样。我的做法是示例至少给三组:正常请求、边界请求、失败请求,每组都带完整请求和响应。

再进一步,把示例变成自动化用例。接口定义里写好的示例,直接生成测试用例,每次构建都跑一遍,跑不通就构建失败。这样一来文档和实现就不可能脱节。这件事的投入产出比极高,因为它一次性解决了“文档说的是 A 实现的是 B”这个顽疾,而这个顽疾在对外场景下的破坏力极大,对接方会因此完全丧失对文档的信任,之后每个字段都要来问一遍。

4.4 灰度开关和降级预案

第十五个点关于故障应对。对外接口必须假设自己会出事:下游挂了、数据库慢了、流量突增了。出事的时候,有没有开关能快速止血,决定了事故的时长。

最基本的两个开关:一个是功能开关,能单独关掉某个非核心能力,保住主流程;一个是降级开关,在依赖不可用时返回兜底数据或者明确的稍后重试提示,而不是让请求一直挂着把线程池耗光。这两个开关要能通过配置中心实时生效,不能靠发版。

降级返回的内容也要设计。直接返回一个空结果比返回错误更危险,因为对接方无法区分“真的没有数据”和“服务降级了”,可能基于空数据做出错误决策。正确做法是返回明确的降级标识,让对接方知道这次结果是不可信的。同理,超时时间要设得克制,不要一个请求挂三十秒,那样在故障期间会把调用方的连接池全部占满,一个服务的故障会顺着调用链放大成一片故障。这个连锁反应的破坏力,比原始故障本身大得多。

4.5 废弃接口要有公告期和兼容窗口

第十六个点是生命周期的收尾。接口总要下线,但下线方式决定了你是体面退役还是制造事故。我见过直接停掉接口的,第二天对接方业务全挂,因为对方根本不知道有这么回事。

规范做法是三步:先标记废弃,在文档和响应头里明确提示该接口已废弃、建议迁移到哪个新接口、计划下线时间;再观察调用量,通过请求标识和调用方标识统计还有谁在调,主动联系;最后在公告期结束后下线,公告期至少一个月,重要接口给三个月。下线前一周再发一次提醒,下线当天保留一段时间的兜底返回(比如返回明确的迁移提示而不是直接 404)。

这里有个细节容易被忽略:废弃提示要能让对接方在代码里感知到。只在文档里写,对方不看文档就永远不知道。放在响应头里,对方的日志和监控能捕获到,才有可能推动他们迁移。我在实际项目里会统计废弃接口的调用方分布,按调用量排序,优先联系大头,这样能在公告期内把绝大部分流量迁走,剩下的长尾再单独处理。

5. 十六个点的落地清单与一次真实排查复盘

5.1 十六个点速查表

把上面十六条压成一张表,评审时逐条对照,比翻文档快得多。

编号检查点一句话判断标准
1命名自解释不看文档能猜出语义
2校验前置脏数据进不了业务层
3响应包体统一全站一套解析代码
4错误码分层看码能判断责任方
5幂等声明重试不会重复扣款
6版本在路径老版本代码不会因迭代崩
7列表规约统一分页参数全站一致
8格式写死时间金额枚举无歧义
9契约颗粒度必填边界默认值齐全
10容量约定批量上限与限流明确
11异步可靠重试去重确认签名齐备
12扩展有秩序新增字段也有登记
13全链路标识报错截图能直接定位
14示例可执行复制粘贴能跑通
15开关可止血故障时不用发版
16废弃有流程下线前有公告和联系

这张表我自己用了很久,最大的价值不是防止遗漏,而是让评审有共同语言。以前评审接口,讨论容易飘到实现细节上;现在对着表过,五分钟就能把明显的问题挑出来,剩下的时间再深入聊业务合理性。

5.2 一次“昨天好今天挂”的完整排查链路

回到开头那个事故,我把排查过程完整走一遍,因为它同时踩了上面好几个点,很适合当反面教材。

第一步是拿请求标识。当时接口还没有统一带标识,我只能让对接方提供调用时间、接口路径和请求参数,靠时间窗口在日志里捞,捞了十几分钟才定位到。这一步就暴露了第十三个点的缺失。

第二步是比对请求参数。发现对方传的字段值本身没问题,格式也对,说明不是参数校验的问题。继续往下看响应,发现返回里有个字段是数字,而对面的代码按字符串处理,解析直接抛异常。

第三步是查变更记录。当天上午我们发过一个版本,把某个表示数量的字段从字符串改成了数字,理由是内部统一类型。这个改动在内部自测里完全没问题,因为调用方都是自家服务,跟着一起改了。但对外没有公告,也没有保留原类型,属于典型的违反第六条“只增不改”。

第四步是定修复方案。当天没法回滚(因为下游其他系统已经按新类型写了),只能在响应里同时保留字符串和数字两个字段,字符串字段标记为兼容用途,等对方全部迁移完再下掉。同时补上了变更公告流程和接口变更的强制评审。

这个事故的复盘结论只有一句话:内部视角的“小改动”,在对外视角下都是破坏性变更。这句话后来被我贴在评审模板的第一行。顺带说一句,那次事故之后我们把接口定义和文档做了同源生成,示例自动跑测试,同类问题再没出现过。

5.3 新人最容易忽略的三个细节

带过几批人之后,我发现有些点是反复被忽略的,跟经验关系不大,跟思维方式关系很大。

第一个是默认值的设计。新人写接口习惯于“不传就报错”,觉得这样严谨。但对外场景下,大量可选参数不传是常态,一律报错会让对接方很难用。合理的做法是给有业务意义的默认值,并把默认值写进文档。当然,涉及金额、权限这类敏感参数不该有默认值,必须显式传。这个区分需要业务判断,不是纯技术问题。

第二个是错误提示的措辞。新人写的提示往往是给开发看的,比如“参数校验失败:field amount invalid”。对外接口的提示应该面向调用方的开发,说清楚哪个字段、什么规则、期望什么,最好还能给个正确示例。措辞这件事看着小,但它直接决定了对接方是十分钟解决还是来回问一天。

第三个是变更的影响面评估。新人改接口时习惯只看代码调用方,不看实际使用方。对外接口的真实使用方可能藏在各种地方,有的甚至是对方系统里的一个定时任务,平时不跑,改了之后一周才炸。所以任何变更都要基于调用统计来评估,没统计就先补统计,再谈变更。这个习惯一旦养成,线上事故会少很多。

最后再分享一个我自己一直在用的做法:每个对外接口上线前,我会假装自己是对接方,从零开始写一段调用代码,只用文档,不看我自己的实现。写的过程中卡住的每一处,都是文档或者设计的问题。这个自测花不了半小时,但能挑出大部分体验问题。等你真的被对接方追着问过几次之后,就会发现这半小时特别值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询