例外与否?如果“是” - 检查与否?

时间:2011-08-09 18:32:06

标签: oop language-agnostic exception-handling

我认为这涉及到一个广泛的主题,但是当一切都以最佳方式完成时,除了理想的变体之外,处理程序工作流程的最佳方法是什么。

让我们更具体一点:

一个类有一个方法,该方法对其参数进行操作并返回结果。 e.g:

public Map<Object,OurObject> doTheWork(OtherObject oo);

我排除的一个可能结果是,如果有其他方式,那么返回null,但是理想。

处理这种情况是否有正确的方法(“银弹”或所谓的“最佳做法”)?

我看到其他三个结果:

1 - 该方法返回EMPTY_MAP;

2 - 该方法已检查异常;

3 - 抛出RuntimeException;

如果对该问题没有一般正确答案 - 应该考虑哪些条件?

关于合同设计的原则(简而言之,方法的责任是处理输出,假设输入参数是正确的) - 抛出任何异常的方法是否正确,或者最好返回空结果虽然结构正确(例如非空)

6 个答案:

答案 0 :(得分:7)

返回null就像为某人设置陷阱。 (在像HashMaps这样的情况下,我们已经过训练以寻找空值,因此可以选择先例。)用户必须知道要注意空值,并且他们必须编写一个替代路径来处理这种情况(这听起来很像处理异常),或者冒着NPE的风险(在这种情况下,异常会被抛出,只是信息量较少,距离原始问题发生的地方一定距离,所以有关出错的信息将是丢失)。

返回一张空地图会让人不清楚是否有任何问题。像返回null一样没有伤害,但它完全是模棱两可的。如果以某种方式返回地图数据纯粹是一种尽力而为的事情而且用户并不需要知道,这可能没问题。 (但这种情况非常罕见。)

如果您希望用户能够对异常做任何事情,那么抛出已检查的异常可能是合适的。

如果用户无法处理异常,或者由于编程错误或由于测试期间应该捕获的内容而导致异常,则可以使用未经检查的异常进行参数化。关于应该检查什么以及应该取消选择什么,存在很大的分歧空间。

答案 1 :(得分:3)

哪个选项对被叫者最有利?如果您需要知道的是一个空映射或返回null,那就没问题。如果您需要更多信息,那么例外将是更好的选择。

对于什么类型的异常,如果被调用者确实需要做某些事情才能恢复,那么检查异常是合适的。但是,未经检查的异常可能更加清晰。

至于返回null或空映射,它取决于被调用者将使用它做什么。如果您希望被调用者获取该地图并将其传递到其他地方,那么空地图是更好的选择。

答案 2 :(得分:2)

如果您的方法中的某些内容由于输入错误而中断,则用户需要知道。因此,例外是最好的方法。返回空数据或空数据可能会使用户认为没有任何错误,这绝对不是您想要的。

答案 3 :(得分:2)

我敢打赌,stackoverflow中有很多好的答案。在我搜索它们之前:

  1. 仅在异常情况下引发异常 - 它们不用于正常控制流。
  2. 当调用者应该能够从异常中恢复时,抛出已检查的异常
  3. 当调用者可能无法从异常中恢复时,抛出未经检查的异常,例如由于编程错误而抛出的异常。
  4. 如果是正常状态,则应返回空集合。特别是当结果是集合时,返回值不应为null。如果返回值为null,则应清楚地记录。如果需要对返回状态进行更复杂的分析,那么使用适当建模的结果类可能会更好。

答案 4 :(得分:1)

这完全取决于doTheWork的问题有多大。

  • 如果问题太大,应用程序可能需要关闭,则抛出RuntimeException。

  • 如果被调用者可能能够从问题中恢复,则CheckedException很常见。

  • 如果空Map没有任何意义,那么它可以用作返回,但是您必须小心,在成功的情况下,空Map不是有效值。

  • 如果你只返回一个null,我建议在Javadoc中记下关于返回值的注释。

答案 5 :(得分:1)

在许多情况下,最佳模式是try / do模式,其中许多例程具有两种变体,例如TryGetValue()和GetValue()。它们旨在处理三种情况:

  1. 该对象获得成功
  2. 由于调用者可能合理预期的原因,无法获取该值,并且系统状态是调用者在发生此类故障时所期望的。
  3. 无法获取该值,由于某种原因调用者可能没有预料到,否则系统状态会以调用者不期望的方式被破坏。

try / do模式背后的想法是有时候调用者会准备好处理失败,但是有时候调用者在失败的情况下唯一能做的就是抛出异常。在后一种情况下,对于未能抛出异常而不是要求调用者执行此操作的方法会更好。