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

时间:2010-10-19 15:29:28

标签: exception exception-handling return-value

我在Should a retrieval method return 'null' or throw an exception when it can't produce the return value?Should functions return null or an empty object?找到了问题,但我认为我的情况完全不同。

我正在编写一个由Web服务和客户端组成的应用程序。 Web服务负责访问数据并将数据返回给客户端。我设计我的应用程序是这样的:

// web服务

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。你有什么评论?有没有更好的方法来解决这个问题?

谢谢。

11 个答案:

答案 0 :(得分:4)

在您的情况下,您的Web服务中已经以某种方式抛出并处理了异常。

返回null有一个好主意,因为客户端代码可以知道您的Web服务中存在错误的内容。

就客户而言,我认为你的方式很好。我认为没有理由抛出另一个异常(即使你不再在Web服务中)。

我这样说,因为从技术上讲,没有任何因素导致客户端代码出错。您只是从Web服务获取错误数据。这只是处理来自外部来源的潜在错误输入的问题。

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

请确保以不会导致客户端代码崩溃的方式处理data == null条件。

答案 1 :(得分:4)

一般情况下,我尝试以这样的方式设计我的web服务,即它们返回某种标志,指示是否存在技术/功能错误。 另外我尝试返回一个复杂的对象,结果不仅仅是一个字符串,所以我可以返回如下内容:

result-> Code =“MAINTENANCE” result-> MaintenanceTill =“2010-10-29 14:00:00”

所以对于一个应该给我一个dataEntities列表的webservice,我将返回类似的内容:

<result>
    <result>
        <Code>OK</Code>
    </result>
    <functionalResult>
        <dataList>
            <dataEntity>A</dataEntity>
        </dataList>
    </functionalResult>
</result>

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

答案 2 :(得分:2)

我使用的所有Web服务都返回对象,而不是简单的数据类型。这些对象通常包含名为bool的{​​{1}}值,可让您快速测试是否信任返回的数据。在任何一种情况下,我认为抛出的任何错误都应该是无法解决的(即无意识的),因此表明服务本身存在问题。

答案 3 :(得分:2)

我认为在做出决定时可能需要考虑几个因素:

  • 用您使用的语言(如果它不是网络服务)执行此操作的惯用方法是什么?
  • 你的soap / webservice库有多好(它是否传播异常或是否)
  • 客户做什么最简单

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

客户端:

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

答案 4 :(得分:2)

你的第一个问题是“不返回null的规则”。我强烈建议重新考虑这一点。

返回SoapException是一种可能性,但是就像已经提到的hacktick一样,最好使用状态标志{Success,Fail}返回来自Web服务的每个响应的复杂对象。

答案 5 :(得分:1)

我认为这一切都归结为客户是否可以使用任何信息来确定没有返回数据的原因。 例如 - 如果没有返回数据,因为在GetSomeData中调用的(例如sql)服务器已关闭,并且客户端实际上可以对该信息执行某些操作(例如,显示相应的消息) - 您不希望隐藏这些信息 - 抛出错误可以提供更多信息 另一个例子 - 如果parameter为null,并且导致异常..(虽然您可能应该在代码中先前处理过..但是你明白了) - 应该抛出一个合适的(提供信息的)例外。

如果客户端根本不关心为什么他没有得到任何数据,你可能会返回null,无论如何他都会忽略错误文本而且他的代码看起来都一样..

答案 6 :(得分:1)

如果您的客户端和服务在不同的计算机或不同的进程上运行,则不可能从服务中抛出错误并将其捕获到客户端上。如果你坚持使用异常,你可以期望的最好的是客户端上的一些代理来检测错误条件(null或其他约定)并重新抛出新的异常。

答案 7 :(得分:0)

处理例外的一般做法是,在正常情况下预期流量顺序,因为由于资源不可用或预期输入而无法完成序列。

在您的情况下,您仍然需要决定如何让客户端代码对null或异常做出反应。

答案 8 :(得分:0)

当发生任何不良事件时,如何传入一个委托来调用?如果那是外部可能想要的,或者让函数返回null(如果外部代码将检查它),或者可能采取其他一些操作,则委托可以抛出异常。根据传递给委托的信息,它可能能够以允许继续处理的方式处理问题条件(例如,委托可能在调用的前几次设置'重试'标志,以防片状网络连接是预期的)。委托人也可以记录在异常被捕获时不存在的信息。

PS - 最好将自定义类传递给检测到问题的委托。这样做将允许该方法的未来版本向委托提供附加信息,而不会破坏任何期望更简单信息的实现。

答案 9 :(得分:0)

建议在同一进程空间中使用例外。在整个流程中,只有通过信息才能评估成功/失败。

答案 10 :(得分:0)

  • 由于您是Web服务的客户端,因此您可以在服务层记录异常并将null返回给客户端,但客户端仍应知道CallGetSomeData是否返回null,因为a)数据不可用或者b)表被锁定时存在数据库异常。因此,总是很好地了解导致错误的原因,以便在客户端更容易报告。您应该在邮件中包含错误代码和说明。
  • 如果您没有使用您的网络服务,那么您应该出于上述相同的原因而绝对抛出异常,客户应该知道发生了什么,并由它们决定如何处理。