自定义Exception类是否应包含业务规则?
自定义Exception类不该包含业务规则,建议用单独类处理后传参
你的核心疑问其实是异常类的职责边界问题——自定义Exception的核心作用是封装错误的状态、元数据,以及和异常相关的行为,绝对不该掺杂业务逻辑(比如数据库实体操作),更适合单独创建业务处理类完成操作后,再传递必要参数给Exception构造器。
原因很直接:
- 单一职责原则:异常类就该专注于“代表错误”,把数据库实体操作这种业务逻辑塞进去,会让类的职责混乱,后续改业务逻辑时还要动异常类,维护成本陡增。
- 复用性差:如果把业务逻辑硬写在异常的静态方法里,这个异常类就和当前业务绑定死了,换个业务场景根本用不了。而单独的业务类可以在不同场景复用,异常类也能灵活适配各种错误场景。
- 测试麻烦:要测试异常里的业务逻辑,必须触发异常才能跑代码,而单独的业务类可以直接写单元测试,不用依赖异常抛出的场景。
- 可读性差:其他开发者看到你的异常类里居然有数据库操作,第一反应肯定是困惑——这到底是异常类还是业务处理类?
结合你的代码,优化后的方案大概是这样:
// 专门处理错误实体的业务类 public class ErrorEntityProcessor { // 这里封装所有和数据库实体相关的操作 public static (IActionResult HttpResult, string? TaskType) ProcessErrorEntity() { // 比如设置错误实体的状态、状态码,保存到数据库 var errorEntity = new ErrorEntity { ErrorStatus = "Failed", StatusCode = 400, ErrorMessage = "业务操作失败" }; // _dbContext.ErrorEntities.Add(errorEntity); // _dbContext.SaveChanges(); // 返回需要传给异常的参数 return (new BadRequestObjectResult(errorEntity.ErrorMessage), "task_type_xxx"); } } // 自定义异常类,只负责封装错误信息 public class CustomException : Exception { public IActionResult HttpResult { get; } public CustomException(IActionResult httpResult, string? taskType = null, string? accessControlExposeHeaders = null) { HttpResult = httpResult; if (taskType != null) Data["some-header"] = taskType; if (accessControlExposeHeaders != null) Data["Access-Control-Expose-Headers"] = accessControlExposeHeaders; } } // 业务代码里的使用方式 public void ExecuteBusinessTask() { // 先处理业务逻辑和数据库操作 var (httpResult, taskType) = ErrorEntityProcessor.ProcessErrorEntity(); // 再抛出异常 throw new CustomException(httpResult, taskType); }
另外提个额外的坑:如果在异常方法里做数据库操作,万一数据库操作失败,会抛出新的异常,直接掩盖了原本要抛出的业务错误,调试起来会非常头疼。
内容的提问来源于stack exchange,提问作者Vagner Wentz
相关产品推荐
相关产品推荐

