错误码应该如何设计?

💁 作者:小瓦匠
💖 欢迎关注我的个人公众号:小瓦匠学编程。微信号:xiaowajiangxbc


错误码的制定原则:快速溯源、沟通标准化。 – 阿里巴巴《Java 开发手册》

前言

在项目开发中,你有没有吃过错误码定义混乱的亏,比如:错误码定义无标准,导致无序扩张;错误码语义表述不清晰;错误定位不精准等问题。

在团队开发中,如果能够制定一套合理科学的错误码规约,就可以有效地避免这些问题,从而降低沟通成本以及程序的维护成本。

需求说明

设计错误码规约前,首先要弄清我们的需求:

  • 让客户端能够感知到 HTTP 请求是否成功,以便客户端决定下一步该如何处理。
  • 错误返回时需要携带错误码和出错信息,可以让开发者通过错误码快速定位问题原因。

错误码设计建议

错误码主要是为了体现业务系统的报错位置及原因,因此在设计时需要给它赋予一定的业务属性。

谁的错?错在哪?

程序开发人员拿到错误码后,必须能够快速知晓错误来源,判断是谁的问题。这也就要求我们设计的错误码首先要具有一定的识别度,方便记忆和对比,并且要有利于团队快速对错误原因达到一致认知。

内容格式统一

错误码应该是统一长度,且内容格式也应该固定的,而不应该是随机编码产生的。其内容可以是一个整数,也可以是一个字符串,但它必须是错误的唯一标识。
通过研究对比各个平台的错误码,我总结出了一个比较实用的错误码设计方案:使用字符数字组合表示,一共有4段组成,不同段表示不同含义。
在这里插入图片描述
合理的内容格式,更便于错误码的管理和使用,一方面我们可以根据业务需求有规则的自行扩展;另一方面通过错误码能够精准地定位到具体是哪里出现的什么错误。

错误语义信息

错误码之外的业务独特信息应由 message 来承载,而不是让错误码本身涵盖过多的具体业务属性。通常在请求出现错误时,我们需要返回的错误描述一般包括:错误码,错误说明以及参考文档(可选)在这里插入图片描述
需要注意的是,错误说明是展示给用户的,最好直接告诉用户“该怎么做”而不是“哪里错了”,并且错误说明中不应该包含敏感信息(例如:堆栈信息)。但是为了方便问题排查,我们可以在系统内部日志中打印详细的错误堆栈信息。

合理使用 HTTP 状态码

当请求出错时,应该合理的返回 HTTP 状态码,以便让客户端感知到 HTTP 是否请求成功。为了更清晰的表述和区分状态码的含义,我们将 HTTP 状态码分成如下5类:
在这里插入图片描述

常用 HTTP 状态码

HTTP 状态码有很多,但是在错误码设计时,我们只需要重点关注下面这些状态码:

  • 200 - 表示请求成功执行
  • 400 - 表示客户端出问题
  • 401 - 表示认证失败
  • 403 - 表示授权失败
  • 404 - 表示资源找不到
  • 405 - 客户端请求中的方法被禁止
  • 500 - 表示服务端出问题
    在项目开发中,我们需要根据实际情况,灵活控制状态码的使用,让客户端的处理更容易。
    综上所述,一个合理的错误返回应该包含 HTTP 状态码和错误码,并且错误码需要对外暴露错误说明,最好还要支持返回参考文档。例如:
HTTP/1.1 405
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 28 Apr 2022 09:55:54 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{"code":"U00N03", "msg":"HTTP请求方式不受支持"}

错误码的具体实现

在系统开发中,推荐使用枚举类,来存放所有错误码、错误说明等信息。比如以系统公共错误码为例:

// 在下面的代码中只给出了部分有代表性的错误码
@Getter
@AllArgsConstructor
public enum CommonErrorEnum implements IResponseEnum {
    /**
     * 成功
     */
    SUCCESS("000000", 200, "SUCCESS"),
    /**
     * 参数校验(Valid)异常
     */
    PARAM_VALID_ERROR("U00P01", 400, "参数校验异常"),
    /**
     * Token已过期
     */
    TOKEN_EXPIRED("U00A02", 401, "Token已过期"),
    /**
     * 未授权,不能访问
     */
    AUTH_INVALID("U00A05", 403, "未授权,不能访问"),
    /**
     * 服务器繁忙,请稍后重试
     */
    SERVER_BUSY("U00S00", 500,"服务器繁忙"),
    /**
     * 未知异常,无法识别的异常
     */
    SERVER_ERROR("U00O99", 500, "未知异常"),
    /**
     * Servlet请求类异常(部分)
     */
    NoHandlerFoundException("U00N02", 404, "资源找不到"),
    HttpRequestMethodNotSupportedException("U00N03", 405, "HTTP请求方式不受支持"),
    HttpMediaTypeNotSupportedException("U00N05", 415, "HTTP请求头的 Content-Type 不受支持"),
    ;

    /**
     * 返回码
     */
    private String code;
    /**
     * 状态码
     */
    private Integer http;
    /**
     * 返回消息
     */
    private String message;
// /**
// * 参考文档 (可选)
// */
// private String reference;
}

总结

总的来说,制定一套错误码规约还是相对容易的,难的是在长期的实践中如何管理并正确使用错误码,保证不被滥用,其复杂程度跟项目规模相匹配。

所以我建议在规约设计时,应该以服务业务为导向,避免过度设计,保持简洁;在管理使用时,应该以先到先得的原则统一审批生效,生效后永久固定。

以上就是我对于错误码规约制定一些想法,规则的制定是灵活的,可变通的,同样也没有绝对的好与坏,只要可以满足你的业务需求就是好的,优秀的。

本人能力有限,各位勉强一观,若能抛砖引玉,不失为一件幸事。


在这里插入图片描述
📌 学习 积累 沉淀 分享
💖 欢迎关注我的个人公众号:小瓦匠学编程! 微信号:xiaowajiangxbc
🔎 扫描二维码或微信搜索 “小瓦匠学编程” 即可关注。

(本文完)

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小瓦匠学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值