首页 > 其他分享 >错误码处理类的设计

错误码处理类的设计

时间:2024-01-29 23:48:46浏览次数:26  
标签:return String 错误 处理 错误码 detailErrorCode 设计 public

云API错误码的设计规则

腾讯云云API错误码分为两级。以点号分隔。

第一级错误码统一由API平台提供 ,业务选择合适的错误场景。第二级错误码可选,业务可自定义。

例如,InvalidParameter.InvalidUserName。其中, 第一级错误码为InvalidParameter,表示这是一个参数错误。第二级错误码为InvalidUserName,表示具体错误的原因是UserName非法。

第一级错误码被整个平台进行监控。并进行错误统计,以及告警。
第二级错误码则一般为业务自定义具体错误码。用来提供FAQ,或者给上游服务更加明确地指示。
对于错误码的设计,我非常不喜欢其他项目中设计为数字的形式。类似100001,100002这样的错误码,每次这样都得进行一次大脑的映射。

详细设计请看 luke的github仓库

如果有更好地设计,欢迎和我探讨。

举例

参数错误

比如InvalidParameterValue.InvalidAppId
一级错误码为:InvalidParameterValue 定义为参数错误。
二级错误码为:InvalidAppId 业务自定义,表示非法的应用Id。

服务端错误

比如InternalError.CantFindConsul
一级错误码为:InternalError 定义为系统错误,或者说服务端错误。
二级错误码为:CantFindConsul 具体定义,表示Consul找不到。

这样的错误码,即使我不去看任何文档,我也能第一时间大概明白发生了什么。

处理云API的错误码类和异常类

如何抛出异常以及如何处理异常是一门学问。

常见的错误处理方式

1. 依据返回值

经常写go的同学比较熟悉。

public class HandleErrorTest {  
    Integer shouldPrint(String input){  
        if(input == null) {  
            return -1;  
        }  
        System.out.println(input);  
        return 0;  
    }  
  
    @Test  
    public void handleErrorByReturnValueIs0(){  
        Assert.assertTrue(0 == shouldPrint("123"));  
    }  
  
    @Test  
    public void handleErrorByReturnValueIs1(){  
        Assert.assertTrue(-1 == shouldPrint(null));  
    }  
}

什么时候需要使用这样的方式呢?

大多数业务中,我们不会采取这样的方式。
只有一种场景:就是我们发现这个函数运行错误的时候,我们需要根据返回值处理,并继续处理下面的逻辑。例如这样。

public void handleErrorDemo(String x){  
    Integer retCode = shouldPrint(x);  
    if(retCode == -1){  
        handleNullCondition();  
    }else{  
        handleOtherCondition();  
    }  
}

返回错误值的本质是为了让我们根据错误值可以按照不同逻辑处理代码。
但是有个重大缺陷,就是在一些列函数调用中,必须依次返回这个错误。

public void func1(String x) int{  
    return func2(x);
}

public void func2(String x) int{
	return shouldPrint(x);
}

在Go代码中,我们可以看到error。所以采用此种方式返回。
但是在Java代码中,强烈不建议这么做。

2. 根据异常处理

Integer shouldPrint2(String input){  
    if(input == null) {  
        throw new RuntimeException("input can't be null");  
    }  
    System.out.println(input);  
    return 0;  
}

一般这样的写法,我在调用侧都不会做任何处理。直接让请求失败即可。

总结

其实大部分的异常情况,我的建议是直接抛出错误。不要吞掉异常!!!少部分带有逻辑的情况,可能需要按照返回错误值的方式来处理。

错误码类的设计

在做任何类设计的时候,我们都是有目标的,即要解决什么问题。这里先列出问题。

  1. 错误码需要区分一级错误码和二级错误码,可以很方便地帮我获取一级错误码。场景:对于上游业务来说,对于参数错误我会忽略,对于内部错误我会告警。
  2. 错误码可以返回更加定制化的信息。比如ResourceNotFound,最好告诉我ResourceId是什么。
  3. 当链路中存在2个以上服务时,我想知道更下游的错误信息。

按照上述目标我们进行设计。

public interface IBizErrorCode {  
  
    String getErrorMessage(Object... args);  
    String getErrorCode();  
    PrimaryErrorCode getPrimaryCode();  
    String detailErrorCode();  
  
    String getDownStreamErrorMessage(Object... args);  
    String getDownStreamErrorCode(Object... args);  
    String getDownStreamPrimaryCode(String downStreamErrorCode);  
}

具体的实现例子如下

  
public enum TestErrorCode implements IBizErrorCode {  
	TestBaseError(PrimaryErrorCode.InternalError, "TestBaseError", "this is a message, reason = {0}", "{1}", "{2}"),  
    ResourceNotFound(PrimaryErrorCode.ResourceNotFound, "UserNotFound", "userId={0} not found", "{1}", "{2}")  
;
    private final PrimaryErrorCode primaryErrorCode;  
    private final String detailErrorCode;  
    private final String errorMessage;  
    private final String downStreamErrorCode;  
    private final String downStreamErrorMessage;  
  
    TestErrorCode(PrimaryErrorCode primaryErrorCode, String detailErrorCode, String errorMessage,  
            String downStreamErrorCode, String downStreamErrorMessage) {  
        this.primaryErrorCode = primaryErrorCode;  
        this.detailErrorCode = detailErrorCode;  
        this.errorMessage = errorMessage;  
        this.downStreamErrorCode = downStreamErrorCode;  
        this.downStreamErrorMessage = downStreamErrorMessage;  
    }  
  
    @Override  
    public String getErrorMessage(Object... args) {  
        return new MessageFormat(this.errorMessage).format(args);  
    }  
  
    @Override  
    public String getErrorCode() {  
        Objects.requireNonNull(getPrimaryCode(), "primaryCode can't be null");  
        String code = getPrimaryCode().getCode();  
        if (StringUtils.isBlank(detailErrorCode())) {  
            return code;  
        } else {  
            StringBuffer stringBuffer = new StringBuffer();  
            stringBuffer.append(code)  
                    .append(".")  
                    .append(detailErrorCode());  
            return stringBuffer.toString();  
        }  
    }  
  
    @Override  
    public PrimaryErrorCode getPrimaryCode() {  
        return this.primaryErrorCode;  
    }  
  
    @Override  
    public String detailErrorCode() {  
        return this.detailErrorCode;  
    }  
  
    @Override  
    public String getDownStreamErrorMessage(Object... args) {  
        return replacePlaceholderWithValue(this.downStreamErrorMessage, args);  
    }  
  
    @Override  
    public String getDownStreamErrorCode(Object... args) {  
        return replacePlaceholderWithValue(this.downStreamErrorCode, args);  
    }  
  
    @Override  
    public String getDownStreamPrimaryCode(String downStreamErrorCode) {  
        return ErrorCodeUtils.getFirstCode(downStreamErrorCode);  
    }  
}

具体的使用场景如下

public void userNotFound(String userId){  
    if(StringUtils.isBlank(userId)){  
        throw new BizException(TestErrorCode.InvalidParameter, "userId can't be blank");  
    }  
    if(StringUtils.equals(userId, "secret user id")){  
        // do nothing  
    }else{  
        throw new BizException(TestErrorCode.UserNotFound, userId);  
    }  
}  
  
@Test  
public void testUserNotFound() {  
    try{  
        userNotFound("luke");  
    }catch (BizException bizException){  
        bizException.printStackTrace();  
    }  
}

一级错误码的设计

云API因为分为一级错误码和二级错误码的概念。
我们从规范可以看到,一级错误码的变化很少。直接设计为枚举类。

public enum PrimaryErrorCode {  
    AuthFailure("AuthFailure"),  
    FailedOperation("FailedOperation"),  
    InternalError("InternalError"),  
    ResourceInsufficient("ResourceInsufficient"),  
    ResourceNotFound("ResourceNotFound"),  
    /**
    省略部分
    **/
    UnsupportedOperation("UnsupportedOperation"),  
    ;    
    PrimaryErrorCode(String code){  
        this.code = code;  
    }  
  
    public String getCode(){  
        return this.code;  
    }  
  
    private String code;  
}

二级错误码的设计

因为是公共包,下面业务的错误码均由业务自己定义,公共包只定义String基础类。

标签:return,String,错误,处理,错误码,detailErrorCode,设计,public
From: https://www.cnblogs.com/patientcat/p/17995605

相关文章

  • 企业如何遵守数据安全法规进行SAP数据脱敏处理?
    随着信息技术的飞速发展,大数据时代的到来使得数据成为国家经济、企业竞争力和个人隐私的重要载体。在这种背景下,数据安全问题日益凸显,各国政府纷纷出台相关法规以保护数据安全。我国也不断完善数据安全法规体系,以确保国家利益、企业发展和公民权益不受侵害。本文将结合中国数据安全......
  • 《实战Java高并发程序设计(第2版)》PDF
    内容简介在单核CPU时代,单任务在一个时间点只能执行单一程序,随着多核CPU的发展,并行程序开发变得尤为重要。《实战Java高并发程序设计(第2版)》主要介绍基于Java的并行程序设计基础、思路、方法和实战。第一,立足于并发程序基础,详细介绍Java进行并行程序设计的基本方法。第二,进一步详细......
  • [职场] 游戏设计求职简历自我评价范文(7篇)
    游戏设计或游戏策划是设计游戏内容和规则的一个过程。下面是游戏设计求职简历自我评价范文,供大家参考。范文1从事游戏3D建模有10年时间,接触了各种美术风格的游戏项目,个人比较擅长欧美卡通、手绘风、个性风格化的美术风格。也接触过2D绘图、3D动作、3D特效、3D场景建模以及关卡地编......
  • java——ip黑名单设计方案(大全+实战)
    java——ip黑名单设计方案(大全+实战)大家好,今天来设计一个ip黑名单功能。即封禁一些类似ddos的非法ip环境:springboot+jdk11本文源码地址:https://gitee.com/xue-shangren/blog-src/tree/master/java-blacklist-design自定义拦截器思路:将黑名单ip存入一个txt文件中(置于resource......
  • 深入理解 C# 编程:枚举、文件处理、异常处理和数字相加
    C#枚举枚举是一个特殊的“类”,表示一组常量(不可更改/只读变量)。要创建枚举,请使用enum关键字(而不是class或interface),并用逗号分隔枚举项:enumLevel{Low,Medium,High}您可以使用点语法访问枚举项:LevelmyVar=Level.Medium;Console.WriteLine(myVar);Enu......
  • 自然语言处理NLP:情感分析疫情下的新闻数据
    原文链接:http://tecdat.cn/?p=12310原文出处:拓端数据部落公众号 新冠肺炎的爆发让今年的春节与往常不同。与此同时,新闻记录下了这场疫情发展的时间轴。▼为此我们分析了疫情相关的新闻内容、发布时期以及发布内容的主题和情感倾向这些方面的数据,希望通过这些数据,能对这场疫......
  • 深入理解 C# 编程:枚举、文件处理、异常处理和数字相加
    C#枚举枚举是一个特殊的“类”,表示一组常量(不可更改/只读变量)。要创建枚举,请使用enum关键字(而不是class或interface),并用逗号分隔枚举项:enumLevel{Low,Medium,High}您可以使用点语法访问枚举项:LevelmyVar=Level.Medium;Console.WriteLine(myVar);En......
  • 记一次MySQL从节点服务器宕机重启后,从节点出现主键冲突异常的处理
    环境MySQL5.7非GTID模式多线程复制。现象某MySQL数据库从节点因故障宕机(因故障直接宕机,非正常关闭),重启之后发现复制状态异常,showslave的结果中Slave_SQL_Running为No,错误代码为1062errorcode,从系统表performance_schema.replication_applier_status_by_worker以及errorl......
  • [职场] 游戏美术设计行业概况
      随着近年来平面媒体盛行与数字艺术的运用,电子游戏已成为八大艺术:绘画、雕刻、建筑、音乐、诗歌(文学)、舞蹈、戏剧、电影之外的某种艺术形式,即第九艺术。游戏领域的所包含的游戏美术行业更是备受关注,游戏美术设计行业概况你了解多少呢?小编带你了解。游戏美术设计已经被教......
  • [错误处理]Support for password authentication was removed
    2021年8月13日github修改了验证的方法,相关的密码不能够直接输入,需要通过相关的秘钥token进行输入。因此我们需要在自己的账户生成对应的token才可以正常的在本地push对应的代码到远程github上。具体的方法如下:我们按照这个帖子操作一下:有效期可以设置为永久,防止到时候过期......