我应该返回null还是抛出异常?

8
我发现这里有一些问题:当检索方法无法生成返回值时,应该返回“null”还是抛出异常?函数应该返回null或空对象?,但我认为我的情况有所不同。
我正在编写一个由webservice和客户端组成的应用程序。webservice负责访问数据并将数据返回给客户端。我设计我的应用程序如下:
//webservice
try
{
   DataTable data = GetSomeData(parameter);
   return data
}
catch (OopsException ex)
{
   //write some log here
   return null; 
}

//客户端:

   DataTable data = CallGetSomeData(parameter);
   if(data == null) 
   {
      MessageBox.Show("Oops Exception!");
      return;
   }

对于不返回 null 的规则,我认为不应该只是重新抛出异常并让客户端捕获 SoapException。您有何评论?是否有更好的方法来解决这个问题?

谢谢。


异常允许您加强您的后置条件。它们也与语言、风格和编码约定密切相关;但您尚未指定任何内容。 - Roger Pate
这看起来像是asp.net,我认为?你应该相应地标记它。 - RMorrisey
11个回答

4
通常,我尝试设计我的Web服务,以便它们返回某种指示是否存在技术/功能错误的标志。此外,我尝试返回一个复杂对象作为结果,而不仅仅是一个字符串,以便我可以返回诸如以下内容的东西:
result-> Code =“MAINTENANCE” result-> MaintenanceTill =“2010-10-29 14:00:00”
因此,对于应该获取数据实体列表的Web服务,我将返回类似以下内容的东西:
<result>
    <result>
        <Code>OK</Code>
    </result>
    <functionalResult>
        <dataList>
            <dataEntity>A</dataEntity>
        </dataList>
    </functionalResult>
</result>

因此,发生在我的Web服务后面的所有故障都隐藏在错误结果中。 调用我的Web服务时开发人员必须关注的唯一异常或错误是在Web服务之前可能发生的异常或错误。


4

在您的情况下,已经有一个异常被抛出并在您的 Web 服务中得到了处理。

在这种情况下返回 null 是个好主意,因为客户端代码可以知道您的 Web 服务出现了错误。

对于客户端,我认为您现在的方式很好。我认为没有理由再抛出另一个异常(即使您已经不在 Web 服务中)。

我这么说是因为从技术上讲,在客户端代码中没有任何错误发生。您只是从 Web 服务中获得了错误数据。这只是处理来自外部源的潜在错误输入的问题。

个人而言,作为一个经验法则,当我得到坏的数据时,会避免抛出异常,因为客户端代码无法控制。

只需确保以一种不会导致客户端代码崩溃的方式处理 data == null 条件即可。


2

在做决定时,我认为有几个因素需要考虑:

  • 如果不是使用webservice,那么用当前语言的惯用方式是什么
  • 你的soap/webservice库有多好(是否传播异常)
  • 客户端最容易做什么

我倾向于让客户端在库的限制范围内做最简单、最惯用的事情。如果客户端库没有自动恢复序列化异常的功能,我可能会用一个带有此功能的库来包装它,以便我可以进行以下操作。

客户端:

try:
  # Restore Serialized object, rethrow if exception
  return CallGetSomeData(parameter);
except Timeout, e:
  MessageBox.Show("timed out")
except Exception, e:
  MessageBox.Show("Unknown error")
exit(1)

WebService:

try:
  return GetSomeData(parameter) # Serialized
except Exception, e:
  return e # Serialized

2

我使用过的所有WebServices都返回对象,而不是简单的数据类型。这些对象通常包含一个名为Successbool值,让您能够快速测试是否信任返回的数据。无论哪种情况,我认为抛出的任何错误都应该是不可捕获的(即非故意的),因此表示服务本身存在问题。


2
您的第一个问题是“不返回null的规则”。我强烈建议重新考虑这个规则。
返回SoapException是一种可能性,但像hacktick已经提到的那样,最好在每个Web服务响应中返回带有状态标志{成功,失败}的复杂对象。

1

我认为这归结于一个问题,即您的客户是否可以使用任何信息来解释为什么没有返回数据。
例如 - 如果没有返回数据是因为(假设)在调用GetSomeData中的(例如sql)服务器已关闭,并且客户端实际上可以使用该信息执行某些操作(例如显示适当的消息)- 您不希望隐藏该信息 - 抛出错误更具有信息性。
另一个例子 - 如果parameter为空,并且导致异常..(虽然您可能应该在代码中早些时候处理它..但您明白我的意思)- 应该抛出适当的(信息性)异常。

如果客户根本不关心为什么没有返回任何数据,则可以返回null,他将忽略错误文本,而他的代码看起来也一样..


1
如果您的客户端和服务运行在不同的机器或进程上,那么从服务中抛出错误并在客户端捕获将是不可能的。如果您坚持使用异常,最好的方法是在客户端上使用代理来检测错误条件(无论是 null 还是其他约定),然后重新抛出新的异常。

0
处理异常的一般做法是,在正常情况下期望流程序列完成,但由于资源不足或期望输入不存在而无法完成序列。
在您的情况下,您仍需要决定您希望客户端代码如何对空值或异常做出反应。

0
如何传递一个委托以在发生任何错误时调用?该委托可以抛出异常(如果外部代码需要),或者让函数返回null(如果外部代码将检查它),或者可能采取其他操作。根据传递给委托的信息,它可能能够以允许继续处理的方式处理问题条件(例如,委托可能在第一次调用时设置“重试”标志,以防预期存在不稳定的网络连接)。委托还可以记录信息,这些信息在捕获异常之前可能不存在。
另外,最好将自定义类传递给检测到问题的委托。这样做将允许方法的未来版本向委托提供附加信息,而不会破坏期望更简单信息的任何实现。

0

建议在同一进程空间中使用异常。跨进程,只有通过信息才能评估成功/失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接