【问题标题】:Returning values vs returning error codes?返回值与返回错误代码?
【发布时间】:2011-12-04 21:21:19
【问题描述】:

这是一个通用编程问题,与任何特定语言无关。

新程序员通常会编写一个计算某个值的方法,然后返回该值:

public Integer doSomething()
{
   // Calculate something
   return something;
}

public void main()
{
  Integer myValue = doSomething();
}

但是当something的计算过程中出现异常时,处理异常的最佳方式是什么,尤其是在给用户反馈的时候?如果您尝试/捕获something 的计算并且如果捕获到异常,您会返回什么?没有计算任何东西,所以你返回 null 吗?一旦你返回它(不管它是什么),你是否需要在父方法中再次尝试/捕获来检查是否返回了有效值?如果没有,那么确保给用户一些反馈?

我在表格的两边都听到过关于从不返回值的争论,而是将计算值设置为指针或全局变量,而是只从方法返回错误代码,然后(在父方法中)简单地处理相应的错误代码。

对此是否有最佳实践或方法?是否有任何好的资源可供人们访问以了解有关处理此问题的最佳方法的更多信息?

更新说明

考虑以下代码:

public void main()
{
  int myValue = getMyValue();

  MyUIObject whatever = new MyUIObject();
  whatever.displayValue(myValue); // Display the value in the UI or something
}

public Integer getMyValue()
{
  try
  {
    // Calculate some value
  } catch (exception e) {
    // ??
  }
  return value;
}

我调用该方法来获取一些 int 值,然后返回它。回到main(),我对这个值做了一些事情,比如在这种情况下在日志中显示它。通常我会在 UI 中为用户显示该值。

无论如何,如果在getMyValue() 中捕获到异常,那么value 是否会返回但它为空?那么main() 会发生什么?我是否也必须测试它是否是 main() 中的有效值?

我需要程序相应地处理错误并继续。下面有人建议通过getMyValue() 方法在 UI 中显示适当的信息。我发现了两个潜在问题:

  1. 似乎我会将业务逻辑与(在这种情况下)UI 逻辑混合在一起。
  2. 我必须将MyUIObject 的引用传递给getMyValue() 或其他东西,这样我才能从函数中访问它。在上面的简单示例中,这没什么大不了的,但如果有一堆 UI 元素需要根据 getMyValue() 中发生的情况进行更新或更改,那么将它们全部传递可能有点多......李>

我已经阅读了很多关于这一切的基础知识,但我似乎无法为上述情况找到一个直接的答案。我感谢任何帮助或见解。

【问题讨论】:

  • 这是什么语言?那么,我们可以为您提供更具体的参考。

标签: exception exception-handling error-handling error-code


【解决方案1】:

我认为您不太了解异常。

如果你抛出异常,你确实不会从函数中正常返回:

public Integer doSomething()
{
   throw new my_exception();
   // The following code does NOT get run
   return something;
}

public void main()
{
  Integer myValue = doSomething();
}

异常的主要优点是:

  • 您可以编写代码,就好像一切顺利,这通常更清晰
  • 很难忽略异常。如果异常未处理,通常会给出明显而响亮的错误,并带有堆栈跟踪。这与错误代码形成鲜明对比,后者更容易忽略错误处理。

我推荐this post by Eric Lippert,它讨论了异常以及何时处理它们是合适的和不合适的。


更新(回应评论):

您完全可以处理异常并继续,您可以通过捕获异常来做到这一点。

例如:

try
{
   // Perform calculation
}
catch (ExceptionType ex)
{
   // A problem of type 'ExceptionType' occurred - you can do whatever you
   // want here.
   // You could log it to a list, which will be later shown to the user,
   // you could set a flag to pop up a dialog box later, etc
}

// The code here will still get run even if ExceptionType was thrown inside
// the try {} block, because we caught and handled that exception.

这样做的好处是您知道出了什么问题(从异常类型),以及细节(通过查看ex 中的信息),所以您 希望有您做正确事情所需的信息。


UPDATE 2回应您的修改:

您应该在能够以您想要的方式响应的层处理异常。对于您的示例,您是正确的,您不应该在代码中如此深入地捕获异常,因为您无权访问 UI 等,因此您实际上无法做任何有用的事情。

这个版本的示例代码怎么样:

public void main()
{
  int myValue = -1; // some default value
  String error = null; // or however you do it in Java (:
  
  try
  {
    getMyValue();
  }
  catch (exception e)
  {
    error = "Error calculating value. Check your input or something.";
  }

  if (error != null)
  {
    // Display the error message to the user, or maybe add it to a list of many
    // errors to be displayed later, etc.
    // Note: if we are just adding to a list, we could do that in the catch().
  }

  // Run this code regardless of error - will display default value
  // if there was error.
  // Alternatively, we could wrap this in an 'else' if we don't want to
  // display anything in the case of an error.
  MyUIObject whatever = new MyUIObject();
  whatever.displayValue(myValue); // Display the value in the UI or something
}

public Integer getMyValue()
{
  // Calculate some value, don't worry about exceptions since we can't
  // do anything useful at this level.
  return value;
}

【讨论】:

  • 如果我需要程序继续正常工作,但可能显示某个值没有正确计算,会发生什么?例如,假设我有一个 UI,其中包含 5 个不同的值,这些值被计算然后显示。如果在计算其中一个值期间出现异常,我想以某种方式在 UI 中通知用户,但我希望程序继续工作并仍按预期计算其他值。我不想让我的程序停止工作……我该如何处理?
  • @Jakobud:我更新了我的答案以解决您的评论 - 这有帮助吗?
  • @Jakobud:我添加了另一个更新,以响应您的更新。这有帮助吗?
  • Eric 关于 Vexing Exceptions 的文章已移至docs.microsoft.com/en-us/archive/blogs/ericlippert/…
【解决方案2】:

你写道:

我在表格的两边都听到过关于从不返回值的争论,而是将计算值设置为指针或全局变量,而是只从方法返回错误代码,然后(在父方法中)简单地处理相应的错误代码。

[编辑] 实际上,异常可以看作是错误代码,它与相关消息一起出现,作为程序员的你应该知道你的异常必须在哪里被捕获、处理并最终显示给用户。只要您让异常传播(在被调用函数的堆栈中向下),就不会使用返回值,因此您不必关心处理相关的缺失值。良好的异常处理是一个相当棘手的问题。

正如 jwd 所回答的,我没有看到在方法中引发异常然后在同一方法中处理异常只是为了返回错误值的意义。澄清一下:

 public Integer doSomething(){

     try{

         throw new my_exception();}

     catch{ return err_value;} 

     }

毫无意义。

【讨论】:

  • 您说使用全局变量和指针而不使用异常是最佳实践?这很疯狂!还是只有我误解了你写的内容?
  • 我实际上在思考 Java,异常被视为错误...我应该编辑我的帖子:p
  • 如果您说error 并想到exception,就很难理解您的意思。 ;-) 顺便提一句。 Java 是一个很好的例子,为什么异常比返回错误代码要好得多。它使代码更安全。
【解决方案3】:

异常是面向对象语言 (OOL) 的一个属性。如果您使用 OOL,您应该更喜欢异常。这比返回错误代码要好得多。您可以找到很好的示例,错误代码方法如何生成比基于异常的代码更长的源代码。例如,如果您想读取文件并对其进行处理并以不同的格式保存。您可以在 C 中毫无例外地做到这一点,但是您的代码将充满 if(error)... 语句,也许您会尝试使用一些 goto 语句,也许使用一些宏来使其更短。但也绝对不透明且难以理解。此外,您通常会忘记测试返回值,这样您就看不到错误并且程序继续运行。这不好。另一方面,如果您使用 OOL 编写并使用异常,则您的源代码专注于“没有错误时该怎么办”,而错误处理则处于不同的位置。对于许多可能的文件错误,只需一个错误处理代码。源代码更短,更清晰等。

我个人绝不会尝试在面向对象的语言中返回错误代码。一个例外是 C++,其中的例外系统有一些限制。

【讨论】:

    猜你喜欢
    • 2012-12-16
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    相关资源
    最近更新 更多