错误码设计原则:常见格式规范、分段含义与版本演化

错误码设计这活儿,说难不难,说简单也不简单。我在项目中见过太多“拍脑袋”定出来的错误码——1001 代表什么?没人记得住。后来新同学接盘,两眼一抹黑,对着 error log 直骂娘。

今天咱们聊聊设计错误码时应该遵循的几个基本原则。说白了,就是让错误码既能读、又能查、还能跟着版本一起长大。

2.1 常见格式规范:给错误码定个“长相”

我个人的习惯是,错误码至少包含两个维度:错误来源 和 错误类型。比如 HTTP API 里常见的 400 Bad Request,来源是客户端,类型是参数问题。

但 SDK 内部错误码比 HTTP 状态码复杂得多。你想想看,同一个网络错误,在 iOS 端、Android 端、服务端可能表示方式完全不同。所以我建议采用 分段式编码,把错误码拆成几个明确的部分。

推荐格式:
[平台标识][模块编号][错误类型][具体原因]

举个例子:

  • 1-0201-003:1 代表 iOS 平台;02 代表登录模块;01 代表网络超时类型;003 代表具体超时场景。
  • 也可以简化为 I_LOGIN_TIMEOUT_003,用枚举字符串 + 数字后缀。

2.2 分段含义:每段都是有故事的

我早期在做一个即时通讯 SDK 时,错误码直接用了四位数字:1001、1002……后来版本迭代到 3.0,新增了十几类错误,数字早就不够用了。拆段之后才彻底解放了。

下面这张图概括了分段错误码的结构和演化关系——

分段错误码结构图 平台标识 模块编号 错误类型 具体原因 示例:1-02-01-003 → iOS / 登录模块 / 网络超时 / 具体场景3 版本演化示意 v1.0 原始码 → v2.0 分段格式 → v3.0 桥接兼容 分段之后,新增模块只需申请新模块编号,不会影响已有错误码 版本升级时可以在网关层做映射,旧码自动转为新格式

分段的具体含义我一般这样定:

  • 平台标识(1位数字或字母):比如 1=Android、2=iOS、3=Server、4=Web。虽然 SDK 通常只跑在一个平台,但文档里混在一起时能快速定位。
  • 模块编号(2位数字):01=初始化、02=登录、03=消息、04=推送……按照功能域划分,未来扩展时 +10 跳号预留。
  • 错误类型(2位数字):01=超时、02=参数校验、03=授权失败、04=资源不足、05=服务器拒绝……
  • 具体原因(3位数字):这个数字只在模块内部定义,可以由后端 SDK 团队自由使用。

你可能会问:“为什么不直接用英文单词?” 我试过,但跨语言环境时英文单词可能被国际化截断。数字是通用的。

2.3 版本演化:错误码也得“长个儿”

SDK 有版本,错误码自然也有生命周期。我记得有一次,一个老版本 SDK 上报了 4000 错误码,运维同学翻遍文档没找到。后来发现那是 v1.0 的“设备被踢出群”,到了 v2.0 改成了 3-02-03-001,旧码没做兼容。

那之后我定了个规矩:

  1. 错误码一旦发布,永不可删除——只可废弃(deprecated),不可销毁。
  2. 每个大版本都要维护一张“映射表”——旧码 → 新码 = 一段映射逻辑。
  3. 废弃码时加上新版本提示——例如 WARN: 错误码 1001 已废弃,请迁移至 1-01-02-000。

小技巧: 在 SDK 内部可以维护一个 legacy_map 字典,运行时自动转换。调用方代码不用改,只调整日志和监控。

2.4 避坑指南:我曾经踩过的三个坑

  • 不要用无意义的自增数字。我曾经直接 ERR_1、ERR_2、……,后来排查问题时根本不知道 57 是什么。一定要加分段含义。
  • 不要频繁重排模块编号。排序一旦发布,就把它当作固定 ID。我在项目里见过某同事把“消息模块”从 03 改成 05,导致所有旧日志查询全部失效。
  • 不要忘记预留跳号。模块编号按 10 的倍数预留:01、11、21……这样中间插入新模块时不用改后面。

特别提醒: 如果你在写多平台 SDK,错误码的枚举定义文件一定要从同一个源(比如 JSON 或 YAML)生成。我曾经手写 iOS 和 Android 两份枚举,结果一个平台多了一个码,排查两天才发现不对等。

2.5 推荐的分段格式参数对比

下面是我整理的不同分段方案,供你参考选择:

方案 示例 优点 缺点
纯数字分段 1-02-01-003 跨语言无歧义;可大规模排序 可读性稍差
字母前缀 + 数字 A02C01S003 紧凑;一人码视觉识别快 大小写易混;分类数量有限
枚举字符串 + 编号 IOS_LOGIN_TIMEOUT_003 自解释;开发人员友好 字符串太长;国际化时翻译困难
UUID 分组(不推荐) err_abc123de 唯一性极强 无法分类查找,日志分析噩梦

我目前最常用的是第一种——纯数字分段。它结构清晰,配合一份错误码文档,团队上手极快。你如果团队规模不大,用枚举字符串也行,但一定要统一命名风格。

小结

错误码设计的核心就三条:

  • 分段:把平台、模块、类型、原因分离开。
  • 稳定:发布即不可删,版本演进时只映射不覆盖。
  • 可查:每个错误码都必须能通过逻辑推导出大概含义,而不是全靠背。

这章我们就聊到这。下次写代码定义错误码时,记得先画个分段表格再说。