程序员的硬伤-异常管理

程序员的硬伤-异常管理享学课堂作者:Peter转载请声明出处!本文试图来阐述一下程序中的异常处理实践,例如避免空值,编写可预测的函数签名,避免空引用异常等。介绍你是不

大家好,欢迎来到IT知识分享网。

享学课堂作者:Peter

转载请声明出处!

本文试图来阐述一下程序中的异常处理实践,例如避免空值,编写可预测的函数签名,避免空引用异常等。

介绍

你是不是经常碰到NullReferenceException?而生产环境中一旦出现这情况,你是不是又花费很长时间,历经千辛万苦,才弄明白问题的根源在哪?像下面这样的代码,你是不是经常写:

return null;

或者:

return 0;

或者:

return -1;

在软件设计里,异常管理是必不可少的,也是软件开发中最重要的主题之一,而且是最被低估的主题之一。开发人员在开发业务需求时可能对日志记录和异常管理一无所知。因为,在正常情况下异常什么也不用做。另一方面,当生产环境中发生异常时,由于缺少日志记录和管理不善的异常,又会导致我们查找问题非常困难。

在本文中,我将编写几个异常处理的实践,如避免null值,编写可预测的函数签名,避免null引用异常等。

背景

第一个问题是,为什么会发生异常?软件程序具有多个功能和子功能。每个函数按顺序执行,可以有输入和输出参数。通常,函数的输出成为另一个输入(图1-a)。在我们编写函数时,我们正在处理这些输入和输出变量。我们有意识或无意识地对这些变量做出一些假设。如果我们的假设有效,我们的代码就能很好地工作(图1-a)。如果某些事情与我们的假设相矛盾,那么我们的代码会出乎意料地行为(图1-b)。为了防止这些意外行为,我们通常会抛出异常。因此,良好的异常管理始于正确的假设。

图1

程序员的硬伤-异常管理

如何做出假设?

假设我们给出了一个包含以下两个函数的接口。这两个函数中的一个返回null (我们不知道哪个),而另一个函数在客户不存在的情况下抛出异常。

Customer GetCustomerByEmail(String email);
Customer GetCustomerById(int customerId);

当我们像下面这样使用时:

Customer customer = customerProvider.GetCustomerByEmail(email);
//Should I check null value?
CallCustomer(customer.PhoneNumber);

我们应该在使用customer变量之前检查null值吗?即使我们知道这一点,我们也很容易忘记检查。我们也可能编写不必要的 – null检查块,它会使我们的代码变得混乱。

但是如果我们知道函数永远不会返回null值,那么我们就不必编写不必要的null-checking块。如下面这样

//A SaleOrder has always an existing customer.
Customer customer = customerProvider.GetCustomerById(order.CustomerId);

客户在数据库中不存在的情况是意外行为。所以最好在这里抛出异常。不要忘记记录有用的信息或者自定义新的异常类。这样,使用者就不用关心空值的情况了。

public Customer GetCustomerById(int customerId){
 Customer customer = db.GetCustomerById(customerId);
 if (customer == null)
 throw new EntityNotFoundException("Customer not found. CustomerId:" + customerId);
 return customer;
}

什么时候处理异常?

大部分情况下,我们不需要处理异常。但是,如果是在某些不重要或可选操作中发生异常,我们希望它不要影响主流程,向日志文件写入警告即可。此时,我们就需要捕获调用链的异常。

使用代码

为了演示上面的情况,我创建了一个示例应用程序。此示例应用程序包含非常简单的模型类,它们只包含我们将要使用的一些属性。

程序员的硬伤-异常管理

项目中的其他文件/类:

  • DBConnection:返回预定义对象的数据库模拟类
  • EntityNotFoundException:自定义异常类
  • Example1,Example2,Example3:三个示例文件。详细信息如下
  • Program:申请的入口点。默认Main方法如下所示:
static void Main(string[] args)
{
 try
 {
 RunExample1(); 
 //RunExample2();
 //RunExample3(); 
 }
 catch (Exception ex)
 {
 LogEx(ex);
 }
 Console.ReadLine();
}

您可以运行其他示例。只需注释掉RunExample1()并取消注释其中一行。

例1

初步代码有不良做法。实际上,根本没有异常管理。当你运行时,你得到一个“ NullReferenceException”。您得不到任何关于该异常的线索。

程序员的硬伤-异常管理

例2

好一点的示例。它会抛出异常或返回值的对象null。现在我们知道在加载City引用的时候发生了异常Address。但是我们仍然不知道哪个订单的地址有无效的City引用。

程序员的硬伤-异常管理

示例3

在第三个例子中,我添加了异常处理块,编写了有用的信息并重新抛出了异常。现在我们知道order,address和city数据导致异常!

程序员的硬伤-异常管理

结论

我解释了如何避免null引用,并编写可预测的方法签名,以帮助开发人员避免不必要的null检查块。希望对你有所帮助。

问题:空对象的返回,应该如何规避?

答:如果为空的情况发生,而此情况属于业务上的意外情况,应该为此情况抛出一个异常类,描述此情况信息。

你的赞和关注是我继续创作的动力~

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/13051.html

(0)
上一篇 2024-03-09 07:15
下一篇 2024-03-09 07:33

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信