Java 返回值:布尔vs int标志vs异常

Java 返回值:布尔vs int标志vs异常,java,api,sdk,Java,Api,Sdk,我需要定义一组函数作为面向公众的SDK接口的一部分,并试图找出向调用方代码发送信号的最佳方式,如果成功或失败,以及如果失败,原因为何 我首先考虑的是返回值和异常。我想我需要将两者结合使用。错误状态/错误引起的错误的例外情况。返回值,用于函数按预期运行并且只希望将调用结果返回给调用方的次数 现在,对于返回类型。我可以使用整数(标志)或布尔值。内部有人认为应该使用布尔,因为它更简单,而且不需要标志。布尔值限制您指定成功或失败,没有任何解释 我将提出两个使用标志的论点。首先,可以返回两个以上的可能值。

我需要定义一组函数作为面向公众的SDK接口的一部分,并试图找出向调用方代码发送信号的最佳方式,如果成功或失败,以及如果失败,原因为何

我首先考虑的是返回值和异常。我想我需要将两者结合使用。错误状态/错误引起的错误的例外情况。返回值,用于函数按预期运行并且只希望将调用结果返回给调用方的次数

现在,对于返回类型。我可以使用整数(标志)或布尔值。内部有人认为应该使用布尔,因为它更简单,而且不需要标志。布尔值限制您指定成功或失败,没有任何解释

我将提出两个使用标志的论点。首先,可以返回两个以上的可能值。允许{成功,失败,失败原因1,失败原因2,失败原因3}。注意:由于这是一个用于在各种硬件设备上实现的接口,因此可能需要能够通知操作失败的原因。e、 g.连接的设备不支持蜂鸣音、没有LCD、不支持嵌入式加密等

谁知道将来会有什么要求呢。返回bool会将您锁定在当前位置,而使用标志允许您在将来具有更大的灵活性。那么,如果将来你永远不需要两个以上的值呢。至少你有选择权

考虑到这将是一个面向公众的SDK,我希望有尽可能多的灵活性,以防止在未来破坏更改


谢谢

在我看来,返回一个值来指示方法调用的结果和抛出一个异常之间的区别在于,一个值只是一个关于发生了什么的通知。对于方法所定义的契约,应将方法调用视为已成功执行。例如,看看是如何定义的

如果一个方法抛出异常,这应该表明该方法的使用不正确,或者在对象/整个系统处于非法状态时调用。例如,当用户的帐户没有足够的积分时,试图为用户购买东西

异常非常适合捕获不同的故障类型:可以通过异常层次结构,也可以通过向异常添加属性,如
getFailureCode()
或将它们组合


我将使用标志指示故障情况,以防必须处理故障。因为忽略返回值非常容易,程序员可能会忽略它,而异常必须主动忽略。

简单的回答是,它根据您的域、客户机和您提供的具体内容而变化很大。如果你还没有,你需要和你的客户坐下来,弄清楚他们将如何使用图书馆。在我脑海中,我会想到以下几件事:

首先,您识别的所有故障类型基本上都是相同的-
不支持操作异常
,并说明原因。是否存在其他故障类型?如果不是,并且使用异常,则可能需要一个类型为/cause/的异常类作为枚举属性

其次,看起来您的许多/大多数/所有方法都将有一种或多种类似的失败类型。这是真的吗?如果是这样,您的API是否提供了确定设备支持哪些功能的方法?考虑这一点:

// Best if I probably don't care about the result if it's not SUCCESS
final Result result = myApiObject.someMethod();
if (result == Result.BEEP_UNSUPPORTED) {
....
} else if (result == Result.NO_DISPLAY) {
....
} else if ...
这是:

// Best if I have to handle every possible failure condition, and I care what
// the failure type is
try {
    myApiObject.someMethod();
} catch (final BeepUnsupportedException e) {
....
} catch (final NoDisplayException e) {
....
}
// Best if I have to consider every possible failure condition, but it probably
// doesn't matter what the failure type is
try {
    myApiObject.someMethod();
} catch (final MyApiException e) {
    if (Cause.BEEP_UNSUPPORTED == e.getCause()) {
        ....
    } else ....
// Best if I know in advance what features I may need
// someMethod() may still return response codes or throw an exception. In this case
// it's possibly OK to make it a RuntimeException, since clients are expected to
// poll for features.
if (myApiObject.supports(Feature.BEEP)
        && myApiObject.supports(Feature.DISPLAY)) {
    myApiObject.someMethod();
} else ...
这是:

// Best if I have to handle every possible failure condition, and I care what
// the failure type is
try {
    myApiObject.someMethod();
} catch (final BeepUnsupportedException e) {
....
} catch (final NoDisplayException e) {
....
}
// Best if I have to consider every possible failure condition, but it probably
// doesn't matter what the failure type is
try {
    myApiObject.someMethod();
} catch (final MyApiException e) {
    if (Cause.BEEP_UNSUPPORTED == e.getCause()) {
        ....
    } else ....
// Best if I know in advance what features I may need
// someMethod() may still return response codes or throw an exception. In this case
// it's possibly OK to make it a RuntimeException, since clients are expected to
// poll for features.
if (myApiObject.supports(Feature.BEEP)
        && myApiObject.supports(Feature.DISPLAY)) {
    myApiObject.someMethod();
} else ...
这是:

// Best if I have to handle every possible failure condition, and I care what
// the failure type is
try {
    myApiObject.someMethod();
} catch (final BeepUnsupportedException e) {
....
} catch (final NoDisplayException e) {
....
}
// Best if I have to consider every possible failure condition, but it probably
// doesn't matter what the failure type is
try {
    myApiObject.someMethod();
} catch (final MyApiException e) {
    if (Cause.BEEP_UNSUPPORTED == e.getCause()) {
        ....
    } else ....
// Best if I know in advance what features I may need
// someMethod() may still return response codes or throw an exception. In this case
// it's possibly OK to make it a RuntimeException, since clients are expected to
// poll for features.
if (myApiObject.supports(Feature.BEEP)
        && myApiObject.supports(Feature.DISPLAY)) {
    myApiObject.someMethod();
} else ...
以下哪项最接近您的客户使用您的系统的方式


第三,这些错误有多致命?我完全同意@Harmlez的观点,必须处理的故障必须是例外。如果没有更多的信息,我们两人都不能告诉你,你的失败是否需要处理。如果客户端主要忽略失败(他们通常希望代码以静默方式失败),或者只关心
成功
!成功
,则返回代码可能正常。如果需要处理失败,那么应该抛出一个选中的异常。您可能希望远离未检查的异常,因为这些故障不是编程错误,客户端可能会正确处理。

除了成功之外,我只看到多种类型的故障。为什么不能将它们包装在异常中?Enum或int标志。同样的问题仍然存在。失败是可以预料的。即不支持操作。异常会改变流程,我的理解是,只有在异常/意外状态下才应使用异常。