平时在软件开发的过程中,首先是要保证功能可以正常运行,满足业务需求,除此之外,还需要考虑代码在异常的时候怎么处理,让程序能够健壮地运行。正确合理地处理异常可以减少程序的 Bug、保证代码质量,当然也不是一件很容易的事。

在日常工作中我们排查错误时经常会遇到这样一些问题,如果没有,说明你做的还不错了:

  • 想通过日志的方式分析错误原因,发现日志记录不完整;

  • 找到错误日志了,记录的是“未将对象引用设置到对象的实例”,也知道代码行数,然而这一行上有多个引用类型的对象,还是不知道真实原因;

  • 问题是偶发的,无法重现。

最终需要还原数据库进行单步调试才能解决问题,然而:

  • 客户的数据库涉密,不能提供;

  • 客户的数据库运行多年,数据量很大,无法快速备份还原;

  • 如果是互联网 Saas 应用,更是难于将库拿到本地进行调试。

所以需要在代码层面、在日志层面来进行优化来达到可以快速定位问题的目的。

dotNET 经典错误

上面这张图,经历过 dotNET Framework 时代的程序员应该都不陌生,这就是经典的「黄页」和经典的 「未将对象引用设置到对象的实例」错误。

首先这个错误显示非常不友好,除了让人知道这个是 dotNET 开发的,别无他用,另外这个错误提示对排查错误也没有帮助,只知道对象为 null 了,但原因是什么并不知道,只能猜,能不能猜中就得看运气了。

正确的错误处理思路

一个系统一般有两类人使用,普通用户和系统管理员。不管是普通用户还是系统管理员,在操作系统时都期望所有的操作是有反馈的,要么正常返回想要的结果,要么给出友好的错误提示,能够指引进行下一步操作。

当出现异常时,可以导向一个专属类型的错误提示页面,也可以以模态的方式弹出错误提示,内容包含:

  • 错误提示,例如:系统异常,请联系管理员,拨打 xxx 、保存失败,请联系管理员;

  • 全局错误码,下面会讲到;

  • 异常编码,可以根据此编码在后台的日志记录快速查询,异常编码使用日期加流水号即可,建议不要使用 Guid,曾经被非技术人员当成是乱码。

如果是系统管理员使用的功能,将真实错误原因显示在错误提示中,我认为也是可以的。

全局错误码

设置全局错误码,可以让管理员在收到反馈的错误时能快速地根据错误码进行问题的定位和找到解决方法。所以需要有公开的全局错误码文档,记录错误的原因和解决方案参考。

大类上可以分为 4xx 和 5xx,4xx 表示前端的参数问题、验证问题等,5xx 表示后端的逻辑问题。

在 5xx 类型中可以再进行细分,例如:

  • 500100:表示数据库操作相关问题

  • 500200:表示列表展示相关问题

  • 等等

异常处理的一些原则

1、在方法中不要返回错误码,因为错误码的信息太单一;
2、抛异常时选择具体的异常类型,不要直接抛出 System.Exception ;
3、错误信息目的是为了让开发人员可以定位问题和解决问题,而不是给最终用户看,给前端用户看的信息要友好易懂;
4、不能吞异常,比如 catch 异常后不做任何处理,如果有些资源需要清理,可以使用 try…finally 或者使用 using ;
5、只有当你知道怎么样从异常中恢复时,才需要去捕获异常,在执行一些操作时,我们可能知道出现错误的原因,但无法恢复,这时不要去捕获异常。

在方法中怎样处理异常?

一个方法中有三个部分:参数、业务逻辑和返回值

参数

引用类型的参数,在方法的开始一定要做非空判断,判断后是抛异常还是继续下面的逻辑这个要根据具体情况来定:

  • 如果参数为 null 时会对后续的业务有影响,就应该抛出异常;

  • 如果我们判断 null 后能做一些初始化处理,能让程序继续正常运行,而且保证业务也是正确的,就不必抛异常。

业务逻辑

业务逻辑的部分分为三种情况:

  • 在方法内部调用其他类型的一个方法,比如 var user= userService.GetUser(); 对 user 的判断,当为 null 时是否抛异常,跟上面参数的逻辑一致;

  • 多个逻辑组合到一起进行判断后,如果不能满足下一步的输入,应该抛出异常;

  • 对于更低一层的调用,有时会进行异常的捕获,当捕获到异常后,应该要抛出符合当前上下文的专有异常信息,更利于定位问题。

返回值

一个方法的返回值可以返回值类型,如 string、int、bool ,也可以返回引用类型,如返回一个 User 对象,不管是返回什么类型,原则是一样的,都需要更具上下文来进行判断。

有个 GetUser 方法来获取用户对象 ,如果根据 Id 没有找到用户,可以直接返回 null ,而不是返回一个空的 User 对象,如果返回空对象,程序不会出错,但前端展示却没有数据,就搞不清是没找到用户,还是找到了但没值;返回 null,可以由上层来决定怎么来处理。

再有个 GetUserList 方法根据条件获取用户集合,如果根据搜索条件没有找到符合的用户,可以返回空对象 List,而不是返回 null 。

对于值类型也是一样,要看上下文,比如 C# 中用来查找字符在一个字符串中的索引位置的函数 IndexOf ,返回的是 int 类型,当找不到的时候返回的是 -1 ,而不是 null 。

最后

好的异常处理可以使我们的程序更加的健壮,也能在出现问题时更好的定位和排查问题,本文的内容偏理论,下一篇以代码示例的方式来进行演练下。

希望本文对您有所帮助。

dotNET:怎样处理程序中的异常(理论篇)?相关推荐

  1. dotNET:怎样处理程序中的异常(实战篇)?

    在上篇 <dotNET:怎样处理程序中的异常(理论篇)> 中讲了一些程序中出现异常怎样处理的理论知识,本文将以代码的方式来进行实践. 环境 dotNET Core:3.1 工具:Rider ...

  2. python中的异常

    1.异常的概念 程序在运行时,如果Python 解释器遇到到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常 程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常 ...

  3. ASP.NET Google Maps Javascript API V3 实战基础篇一获取和设置事件处理程序中的属性...

    ASP.NET Google Maps Javascript API V3 实战基础篇一获取和设置事件处理程序中的属性 <%@ Page Language="C#" Auto ...

  4. Uncertainty Modeling and Optimization-不确定性建模与优化-理论篇(高速更新中)

    Uncertainty Modeling and Optimization-不确定性建模与优化 目录 Uncertainty Modeling and Optimization-不确定性建模与优化 0 ...

  5. PHP ERROR_php中的异常和错误浅析

    本文主要介绍了php中的异常和错误,分享给大家供大家参考学习,下面来一起看看详细的介绍: 一.异常与错误 异常是指程序运行中不符合预期情况以及与正常流程不同的状况.错误则属于自身问题,是一种非法语法或 ...

  6. 一卡通(M1卡)破解过程记录——理论篇

    前些日子在研究学校的一卡通安全,在此记录一下一卡通破解的全过程,仅用作学习交流,切勿用于违法用途 其他几篇: 一卡通(M1卡)破解过程记录--准备篇              获取扇区密钥      ...

  7. 手撸Spring系列8:Spring AOP(理论篇)

    说在前头: 笔者本人为大三在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,发布的文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正. ...

  8. dotnet 从入门到放弃的 500 篇文章合集

    本文是记录我从入门到放弃写的博客 博客包括 C#.WPF.UWP.dotnet core .git 和 VisualStudio 和一些算法,所有博客使用 docx 保存 下载:dotnet 从入门到 ...

  9. 深入浅出Java线程池:理论篇

    前言 很高兴遇见你~ 借助于很多强大的框架,现在我们已经很少直接去管理线程,框架的内部都会为我们自动维护一个线程池.例如我们使用最多的okHttp以及他的封装框架Retrofit,线程封装框架RxJa ...

最新文章

  1. Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比
  2. 7 Papers | MIT学神开源微分太极;北大等提出没有乘法的神经网络
  3. HLG 1349 Graph [floyed]
  4. Linux进程全解8——exec 族函数
  5. 唯品会2017年双11大促技术保障实践,全域提供25万QPS服务能力
  6. RDL(C) Report Design Step by Step 3: Mail Label
  7. 直接在安装了redis的Linux机器上操作redis数据存储类型--hash类型
  8. python批量解压文件_Python 批量解压ZIP和RAR压缩文件(循环验证密码)
  9. 雷电模拟器使用adb命令(采坑)
  10. LCD高抗干扰液晶段码屏显示驱动芯片:VK2C21A/B/BA/C/D 大量应用于音箱/音响面板LCD显示驱动
  11. 微信自定义分享功能实现
  12. 黄褐斑的食疗用什么,姬净美效果不错
  13. 关于R语言中文公开课
  14. FFmpeg入门详解之119:FFmpeg的SDK编程回顾总结并操练
  15. 3分钟掌握自给IP地址
  16. 笔记——流水线基础概念
  17. Mac charles 配置ssl
  18. 全球行情_全球股市中心
  19. OPPO Find5 X909T ColorOS1.0系统精简笔记
  20. 2602 Bone Collector

热门文章

  1. MVC学习九:MVC 特性本质
  2. 构建和实现单点登录解决方案(转载于IBMdeveloperWorks)
  3. LeetCode: 14. Longest Common Prefix
  4. IOS原生地图与高德地图
  5. 发布软件之前,怎样告诉用户怎么用
  6. 食疗去除头屑的小偏方 不错!
  7. java input回车,用java怎样编写加减乘除,从键盘输入,例如:1+2按回车得到
  8. vista磁盘使用100%_如何在Windows 7或Vista中创建和使用密码重置磁盘
  9. 限流算法(记录cyc大佬的专栏)
  10. Oracle数据库IP访问限制(IP白名单黑名单)