异常管理

简介:

介绍

在任何应用系统开发中,异常管理对开发人员来说都是一个关键领域。作为一个开发人员,你应该采用一种合适的、能让你编写健壮且高质量代码的异常管理策略。如果使用得当,异常管理将是一个很强大的概念而且使你的开发工作变的很容易。然而,一个不合适的异常处理将会使你的应用系统性能降低。

 

在你钻研这些之前,要先搞清楚异常管理是什么,这点很重要。一般来说异常就表示“打破系统预定的假设”。“异常”和“错误”是不一样的,为了解释清楚,我们来看两个例子:

示例一

       我们假设你试图向一个文件写入数据,而你的应用程序也认为这个文件在正确的路径上。如果不在,就会抛出一个异常。而话说回来,如果你的职责是跟踪此文件,那么代码里还有(找不到文件的)异常那将是一个不好的编码习惯,这种情况应该被校验代码处理(而不是异常)。

示例二

       再让我们假设一个一般的ASP.NET程序中,你正试图更新数据库中所有必需的字段。你的应用程序认为此数据库连接可用,假设实际上这个连接是不可用的……抛出异常是一个解决方案。而我们又把话说回来,如果更新数据库的必填字段时出现有几个值为空的字段,那抛出异常就没有必要了,这些处理应该由校验代码完成。

如何处理异常

       作为一个开发人员,你应该感受到通过try, catch, finally块来构建一个结构化异常处理机制的优点。.NET框架提供了一大堆异常处理层次来处理不同种类的异常。所有的异常都继承自Exception(基类)。你可以通过继承来实现自定义错误处理以扩展异常处理机制。不幸的是,很多开发人员都误用了这种架构能力。一个随时要记着的事是当一个异常发生在运行时时(这个架构)应该如何运作?一般有以下三种情况:

  1. 忽略异常,让它在调用栈里上升而被其它的catch块捕获。
  2. 捕获异常,同时为你的应用程序执行必要的动作,如果你不想再次在异常中抛出异常的话。
  3. 捕获异常,并用其它异常覆盖它。这样和你的应用程序有更密切的关系。异常覆盖是为了避免打破(架构中的)抽象层次。你可以通过你抛出的异常的InnerException属性指定原异常是什么,这样就可以把你现有的异常用一个新的异常来覆盖了(更与你系统有关的)。为了了解异常覆盖,让我们来看一个能引起IOException异常的方法,你可以在应用级别使用LoadingException 或 FailtoLoadInfoException来覆盖原有的IOException异常,这样比把底层的IOException给用户看到要来的好些。

  经验总结

尽可能在最低级别处理错误。 避免通过异常处理机制将较低级别(DataAccess,Facade)抽象公开给较高级别(UI)。 如果您必须使异常沿栈上移,那么应将较低级别异常转化为对于处理层而言有一定意义的异常(自定义异常)。

 

一个应用程序的异常处理框架应该有以下几种(要求):

    • 探测异常;
    • 执行代码清除;
    • 内部异常覆盖;
    • 内部异常替换;
    • 记录并报告错误信息;
    • 建立能被外部监视的事件以帮助系统操作;

 

在开始你应该建立一个一致的,健壮的异常管理架构,在你所有的系统中应该很好的封装并抽象其记录和报告等的细节。

好的习惯

       以下列出一些不错的提示/建议供你在(设计)异常处理(时)参考:

  • 抛出异常要不小的代价。所以,你应该尽可能地在“异常情况”下进行异常处理,不要去控制正规逻辑流程。比如,以下代码:
void  EmpExits( string  EmpId) {      //  search for employee      if (dr.Read(EmpId)  == 0 //  no record found     {         throw ( new  Exception( " Emp Not found " ));     } }

应该用以下代码:

bool  EmpExits( string  EmpId) {      //  search for employee      if (dr.Read(EmpId)  == 0 //  no record found     {         return false ;     } }

 

  • 避免在循环中捕获异常,如果实在是要捕获,那把整个循环都放在try/catch块里。
  • 采用标准try/catch/finally异常处理方式进行处理,这在托管代码里是被推荐的。最后的Finally块确保异常事件中的资源都被释放掉了。 比如:
SqlConnection conn  = new  SqlConnection( " " );  try  {     conn.Open();      //  some operation      //  some additional operations catch (Exception ex) {      //  handle the exception finally  {      if  (conn  != null &&  conn.State  == ConnectionState.Open)         conn.Close();  //  closing the connection }

 

  • 尽可能的用校验代码而避免使用异常。如果你知道一个可避免的条件可能会出现,那就让它避免。比如,在执行任何操作以前,检查空值(VB里是Nothing),这样可以避免使用异常以及性能问题。 以下代码:
double  result  = 0 try  {     result  =  firstVal / secondVal; }  catch (System.Exception e) {      //  handling the zero divided exception }

应该替换成:

double  result  = 0 if (secondVal  != null &&  secondVal  > 0 ) {     result  =  firstVal / secondVal; }  else  {     result  = System.Double.NaN; }

 

  • 不要为没有必要的情况(原文:reasons)抛出异常。再次抛出异常的开销和实例化一个新异常的开销一样的大,同时再次抛出异常使程序调试工作增加难度。比如:
try  {      //  Perform some operations ,in case of  throw an exception… catch  (Exception e) {      //  Try to handle the exception with e      throw ; }

 

  • 推荐的处理不同的错误的不同的方法是实现一系列的catch块,这看起来好像没有什么,但可以让你的异常处理从特殊走向普通。比如捕获一个和文件有关的异常明显要比捕获一个FileNotFoundException, DirectoryNotFoundException, SecurityException, IOException, UnauthorizedAccessException甚至最后的基类Exception,好的多。
  • ADO.NET 的错误应该通过 SqlException 或 OleDbException来处理。
  • 使用ConnectionState属性来检查连接是否可用要比异常处理好的多。
  • 要常使用Try/Finally,Finally提供了关闭连接的机会。Using语句可以达到同样的效果。
  •         用指定的处理程序来处理异常。在一些情况下如果你知道一些可能的异常那就用相应的异常处理类,比如:

 

try  {      }  catch (SqlException sqlexp)  //  specific exception handler {      }  catch (Exception ex)  //  Generic exception handler  }

 

  • 你的异常处理架构应该可以探测异常并在内部将其覆盖,(或是)使用其它异常将其替换,或是为监视系统而记录和报告这些信息。
  • 推荐大家使用 Microsoft's patterns & practices 团队 提供的Exception Management Application Block。这是一个简单且可扩展的框架用于记录异常信息到事件文件中,你可以自定义它,把日志记录到其它数据源中同时不影响你系统的代码。Exception Management Application Block都是一些由patterns & practices团队开发的很好的代码,并且已经彻底地被Microsoft labs给测试过了。
分类:  ASP.NET
本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2012/11/22/2782227.html ,如需转载请自行联系原作者
相关文章
|
2月前
|
人工智能 监控 安全
2025年国内主流数据治理与数据中台产品大全,国内数据治理厂商推荐
在数字化转型加速的背景下,数据治理与数据中台成为企业释放数据价值的关键。本文聚焦国内市场,精选10款代表性产品——包括瓴羊Dataphin、腾讯WeData、华为DataArts Studio、字节Dataleap、网易数帆EasyData、奇点云DataSimba、袋鼠云DTinsight、亚信AISWare DataOS、星环TDS和数澜Datahub,从核心能力、架构特点与适用场景等维度进行解析。这些产品各具优势,文章建议企业结合自身规模、业务特性与技术基础,选择匹配的数据平台,以实现数据驱动的高质量发展。
2025年国内主流数据治理与数据中台产品大全,国内数据治理厂商推荐
C++ 捕获所有异常并拿到错误原因的方法
C++ 捕获所有异常并拿到错误原因的方法
464 0
【Simulink】示波器图形数据导入Matlab重新绘图的简明教程(论文)
【Simulink】示波器图形数据导入Matlab重新绘图的简明教程(论文)
2246 0
|
6月前
|
关系型数据库 数据库 索引
间隙锁
间隙锁是数据库中用于解决幻读问题的锁机制,主要在可重复读隔离级别下生效。它通过锁定索引记录之间的间隙,阻止其他事务插入新数据,从而保证查询结果的一致性。间隙锁在范围查询、唯一索引不存在记录时等场景触发,既能防止并发插入冲突,也可能降低并发性能并引发死锁。合理配置隔离级别和优化查询条件可减少其影响。
296 0
|
11月前
|
安全 搜索推荐 网络安全
外贸网站应该如何搭建?
建立优质的外贸网站需要进行需求分析、域名选择、SSL证书部署、建站产品选择、便利性和响应式设计以及高质量内容SEO优化。选择合适的模板、部署SSL证书和高质量内容是关键。建站门槛低,节省成本,同时提升用户体验和搜索引擎可见性。
348 2
|
数据可视化 Serverless 数据处理
【优秀python案例】基于python因子分析关于城市发展差异分析中的应用与实现
本文利用Python进行因子分析,揭示了影响中国东西部地区发展差异的关键因素,为促进区域均衡发展和协调增长提供了科学依据。
545 107
【优秀python案例】基于python因子分析关于城市发展差异分析中的应用与实现
|
Java 关系型数据库 API
Spring Cloud微服务面试题
Spring Cloud微服务面试题
670 0
|
机器学习/深度学习 人工智能 语音技术
情感识别与表达:FunAudioLLM的情感智能技术
【8月更文第28天】随着人工智能的发展,语音交互系统越来越普遍。其中,情感智能技术成为提高用户体验的关键因素之一。本文将探讨 FunAudioLLM 如何利用情感识别和表达技术来增强语音交互的真实感,并提供具体的代码示例。
1469 0
|
SQL 关系型数据库 MySQL
如何查看本地公网 IP 地址?
如何找到本地的公网IP?这篇文章帮到你。
1327 3
|
Kubernetes 关系型数据库 分布式数据库
【PolarDB开源】PolarDB与Kubernetes集成:容器化部署的最佳实践
【5月更文挑战第21天】本文介绍了将阿里云的高性能数据库PolarDB与容器编排工具Kubernetes集成的步骤。首先,需准备Kubernetes集群和PolarDB Docker镜像,安装Helm。然后,通过Helm部署PolarDB,设置存储类和副本数。接着,应用配置PolarDB连接信息,打包成Docker镜像并在K8s集群中部署。此外,调整PolarDB参数以优化性能,并使用Prometheus和Grafana监控。本文为PolarDB在Kubernetes中的最佳实践提供了指导。
503 4