请教一个涉及前向兼容的 API 设计问题

160 天前
 xFrank

背景:
我们提供一个 SDK ,有很多 API 供上层应用使用。每次 API 变更都要考虑前向兼容,不能影响已有应用(否则代价巨大)

问题: 假设我有一个 API ,设为 DoA ,当 DoA 出现异常的时候,会通过另一个回调函数 OnError(err)返回错误信息给上层应用。 假设前期的错误码回调设计是这样的( err 是个结构体,包含 code 和字符串):

{1001, "原因 1"},
{1002, "原因 2"},
{1003, "原因 3"}

最近有部分用户提出来,部分错误码设计不合理:原因 2 太粗,需要细化为原因 2a ,2b ,2c 。需求是合理的。

那这个时候整个 OnError 的错误码回调应该如何设计呢?(即能精细化错误码,又要保证前向兼容) 当前想到的几个方案:

方案 1: 直接新增 code 和错误码字符串,

{1001, "原因 1"},
{1002, "原因 2"},
{1003, "原因 3"},
{10021, "原因 2a"},
{10022, "原因 2b"},
{10023, "原因 2c"},

问题:会导致原来只判断 1002 的应用不兼容

方案 2: 新增 code 和错误码字符串,当出现 2a 导致的错误时,回调两次,把 1002 和 10021 都回调一下 问题:上层应用不一定能接收两次回调,或者可能导致上层应用出现一些时序相关的奇怪问题

方案 3: 不新增 code ,通过不同的字符串来标识精细化的错误信息。类似这样:

{1001, "原因 1"},
{1002, "原因 2a"},
{1002, "原因 2b"},
{1002, "原因 2c"},
{1003, "原因 3"},

问题:对开发者不太友好,因为他还需要去解析字符串。。。

大家看下是否有更好的设计?

2003 次点击
所在节点    程序员
27 条回复
sujin190
160 天前
感觉比较好的方式是添加一个 error_details 数组结构化字段,里边详细包含各种细节错误信息,一级的 error_code 只用来表示错误大类别,一般来说 error_code 决定大业务流程方向,在保证 error_code 能完整完成业务流程情况下,error_details 提供细节优化,实际情况下就算后续 error_details 进行调整了不兼容也能保证业务流程能正常完成,只不过纠错、提示或者交互不那么优化而已,毕竟大的业务流程总不能说改就改吧,否则你这兼容性感觉没法弄
iOCZS
160 天前
一般错误有个域的概念,域下面才细分具体的情况,域可以用一个数据范围代替,譬如说 11000-11999 都是某个类型的错误
BiChengfei
160 天前
方案二吧,新增加一个字段,例如原字段:code ,新字段 codeDetail 。只是不明白为啥方案二要分两次回调
13240284671
160 天前
v1,v2 版本
Curtion
160 天前
你的三个方案都要求上层应用做修改才行,这也没有兼容上啊。看起来发布新 SDK 就行, 需要的人更新不需要的人继续用旧版,想升级的人也改(反正他们都得改)
ntower
160 天前
话说你这是向后兼容吧
javalaw2010
160 天前
新增一个 subcode
gaobh
160 天前
大部分都是提供 v1 v2 接口,老接口不断,直到大部分人都迁徙
zhuisui
160 天前
首先:你这是向后兼容,不是向前兼容。。。
xFrank
160 天前
@sujin190 error_details 添加在哪里啊?
@BiChengfei 因为要给老应用回调老 code ,新应用回调新 code
@Curtion 方案 3 可以兼容老的,因为从开发角度看,一般人 if else 里面写的都是 code ,那个字符串都是用来打印提示信息的。方案 3 就要求新的应用纪要判断 code ,也要提取字符串里面的信息来做更多的判断

另外,澄清下,这个场景比较特殊,只要有升级,所有应用都只能跑最新版本。。。
xFrank
160 天前
@iOCZS 你说的错误码分级的情况,当前接口已经已这样的形式开出去了,不能在改了。。。
ilvsxk
160 天前
抛弃用 int 来定义 error code ,用字符串,用 . 来表示业务层级关系,比如:{ "error": "order.edit.network_error"} {"error": "order.edit.no_auth"} ,既表意,又能扩展,也有层级关系。
whoosy
160 天前
@ilvsxk 你这... op 的重点是“兼容”两字
whoosy
160 天前
影响面最小的修改就是方案三
vacuitym
160 天前
不如增加一个二级的 code 和 msg
linauror
160 天前
推荐 sub_code 的形式
magicls
160 天前
我多问一句,你写的
``` json
{1001, "原因 1"}
```

这是你简写了,还是说就是这样的?因为我理解接口再怎么烂,它不应该都是

``` json
{"code":1001, "message":"原因 1"}
```

这样吗?
ZZ74
160 天前
建议用 3 ,问题本质是错误原因定义太宽,2a 2b 其实就是不同错误
ilvsxk
160 天前
@whoosy #13
兼容的话,不管是新增错误码,还是用子错误码还是别的方案,要做兼容都是搞一套新的或者加新的,旧的不动,继续留着。
renmu
160 天前
以前没考虑到,那现在不管你怎么改都会改变原来的语义,那就不要改了,留着以后 v2 大版本不兼容再动

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1056521

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX