空结果与抛出异常可预测但不可避免的失败

时间:2018-05-03 17:09:03

标签: java exception optional

遇到可预测但不可避免的故障的方法的首选设计是什么? 他们应该返回空结果还是在失败时抛出异常?请解释一下你的推理。

我将提供两种示例方法:

  1. Arrays.binarySearch()这样的方法,它返回数组中值的索引。
  2. Tickets.buy(20, 100)。票务机器人尝试使用100美元购买至少20张票。该方法返回已购买的票证列表。
  3. 对于这两种方法,我们假设用户无法预测该方法是否能成功找到匹配。

    如果出现以下情况,方法1可能会失败:

    • 数组不包含所需的值。

    如果出现以下情况,方法2可能会失败:

    • 门票不够。
    • 有足够的门票可供出售,但价格超过100美元。

    Java选择将等效项返回给方法1的空结果,但对方法2执行相同操作不允许您区分这两种错误。选择两种可能的设计有哪些指导原则?

    请注意,虽然这个问题包含两个具体方法,但我正在寻找一般设计指南,而不是上述方法的具体解决方案。

4 个答案:

答案 0 :(得分:1)

最好的方法取决于案例。

案例1: 由于该方法返回找到的元素的索引,如果找不到所需的值,我建议返回-1。坚持几乎每个人都熟悉的众所周知的API,比如indexOf()

案例2: 在这里,我建议使用例外(InsufficientMoneyExceptionOutOfTicketsException,...)。空列表或null不是很有意义,并且不能反映不同的错误情况。 这样您就可以在各自的catch块中正确处理异常。

通常,您必须记住,抛出异常是昂贵的操作,因为必须构建堆栈跟踪。

答案 1 :(得分:1)

这个问题基于意见,就像整个返回null /抛出异常/返回空对象困境一样。

我个人认为返回-1是第一种方法,为第二种方法抛出异常会更好。

single responsibility principle之后,一种方法应该做一件事。

第一种方法的目标是搜索一个元素,它可以找到或找不到它。这是预期行为

第二种方法的目标是买票。与第一种方法不同,它不是检查,如果它可以买票,它就是这样做的。预期的行为是购买机票。 如果该行为未发生,则出现问题,因此应抛出异常

我也认为@ StriplingWarrior的方法可能并不理想,因为如果你不仅仅有两种可能的情况,你就不可能Either<A, B, C, D, E, ...>

RIP。我花了15分钟写了一个答案,我意外地打开了Web控制台并删除了正文。最后保存的答案就像10分钟前一样。我甚至不知道你怎么会意外地这样做。我猜F12DEL有点接近

答案 2 :(得分:0)

通常,您希望将返回类型设为包含您可能需要了解的所有信息的对象。

在Java的早期阶段,通常会返回通常无效的值,例如-1(在Arrays.binarySearch()}或null的情况下),以表示缺少值。更现代的API倾向于返回Optional<>以提供可能没有结果的概念的编译时执行(以及区分&#34;没有结果&#34;和&#34;结果是null)。

Tickets.buy()示例中,您可以拥有Either<String, List<Ticket>>,其中&#34;左边&#34;价值可能是购买失败的原因,并且&#34;权利&#34; value可以是成功购买的门票。

答案 3 :(得分:0)

我最终接受了https://stackoverflow.com/a/77361/14731

中的建议

我的解释如下:

  • 从纯粹的角度来看,如果Arrays.binarySearch()的目的是返回数组中元素的索引,那么当找不到匹配项时它应该抛出异常。没有结果具有负索引的事实是一个方便的事实,它允许我们返回-1。但同样,在理想世界中,这种方法应该抛出异常。如果此方法回答“数组是否包含此元素”并返回boolean这一问题,那么就不需要抛出任何异常。
  • Tickets.buy(20, 100)假设在购买门票时会找到匹配项。如果未找到匹配项,则应抛出异常。