大家好,欢迎来到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