【问题标题】:Should I return null or throw an exception?我应该返回 null 还是抛出异常?
【发布时间】:2011-04-27 13:36:33
【问题描述】:

我在这里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 服务和客户端组成的应用程序。 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。你有什么意见?有没有更好的方法来解决这个问题?

谢谢。

【问题讨论】:

  • 例外情况允许您tighten your post-conditions。它们还与语言、风格和编码约定密切相关;但你没有指定任何一个。
  • 这看起来像是 asp.net,我想?你应该相应地标记它。

标签: exception exception-handling return-value


【解决方案1】:
  • 由于您是 Web 服务的客户端,您可以在服务层记录异常并向客户端返回 null,但客户端仍应知道 CallGetSomeData 是否返回 null,因为 a) 数据不可用,或者b) 表被锁定时出现数据库异常。因此,总是很高兴知道是什么导致了错误,以便在客户端更轻松地报告。您应该在消息中包含错误代码和说明。
  • 如果您不使用 Web 服务,那么您应该明确地抛出异常,原因与上述相同,客户端应该知道发生了什么,并由他们决定如何处理。

【讨论】:

  • 您如何定义“使用您的网络服务”? TIA。
  • “不使用你的网络服务”-“不是你服务的客户端”。这是您编写公开使用的服务(如信用卡身份验证)的时候。
【解决方案2】:

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

返回 SoapException 是可能的,但就像 hacktick 已经提到的那样,最好在 Web 服务的每个响应中返回一个带有状态标志 {Success,Fail} 的复杂对象。

【讨论】:

    【解决方案3】:

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

    结果->代码 = "维护" 结果->MaintenanceTill = "2010-10-29 14:00:00"

    所以对于应该为我提供数据实体列表的网络服务,我将返回如下内容:

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

    所以我的网络服务背后可能发生的每一个故障都隐藏在错误结果中。 开发人员在调用我的 Web 服务时必须关心的唯一异常是可能在 Web 服务之前发生的异常或错误。

    【讨论】:

      【解决方案4】:

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

      • 在您使用的语言中执行此操作的惯用方式是什么(如果它不是 Web 服务)
      • 您的肥皂/网络服务库有多好(它是否传播异常)
      • 客户最容易做的事情是什么

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

      客户:

      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)
      

      网络服务:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

            我认为这一切都归结为您的客户是否可以使用任何信息来了解为什么没有返回数据的问题。
            例如 - 如果因为GetSomeData 中调用的(比如 sql)服务器关闭而没有返回数据,并且客户端实际上可以使用该信息执行某些操作(例如显示适当的消息) - 你不想隐藏该信息 - 抛出错误会提供更多信息。
            另一个例子——如果parameter 为空,这会导致异常。(尽管你可能应该在代码的前面处理过这个问题。但你明白了)——应该抛出一个适当的(信息丰富的)异常。

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

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                【解决方案9】:

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

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

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                    【解决方案11】:

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

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

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

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

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

                    只要确保您处理 data == null 条件的方式不会使您的客户端代码崩溃。

                    【讨论】:

                      猜你喜欢
                      • 2010-12-05
                      • 1970-01-01
                      • 2011-11-09
                      • 1970-01-01
                      • 2012-12-22
                      • 2012-06-08
                      • 1970-01-01
                      • 2016-08-04
                      • 2015-07-12
                      相关资源
                      最近更新 更多