【问题标题】:Making a consistent API, what's less surprising?制作一致的 API,还有什么不那么令人惊讶的?
【发布时间】:2015-02-24 20:02:08
【问题描述】:

我有一个 API,其中有如下属性访问器:

int foo()

有时属性可以为“null”。由于 int 不能为 null,因此使用额外的属性来检查 null。

bool hasFoo()

当人们调用 foo() 时会发生什么? foo() 的实现不会有未定义的行为,而是在内部检查 hasFoo() 和恐慌,这通常会终止线程或进程并显示错误消息。

花车让事情变得更有趣。此 API 中的浮点数有一个空值:NaN。所以对于

float bar()

当 hasBar() 返回 false 时,bar 将始终返回 NaN,这是非常明确的行为。事实上,大多数类型、字符串、日期等都有有效的“空”表示。 ints 和 bool 是奇数,其中 0 可以是有效值。

所以我的问题是,当 hasBar() 为 false 时 bar() 是否也应该恐慌以与 int 和 bool 保持一致?或者可能是整数和布尔值在它们为空时应该返回 0,并且只有通过调用 hasFoo() 才能分辨出真正的 0 和空的 0 之间的区别。什么行为不那么令人惊讶?为什么?

【问题讨论】:

    标签: architecture language-agnostic


    【解决方案1】:

    案例 1:当 hasBar() 为 false 时 bar() 也会恐慌

    这对我来说并不奇怪,就好像我没有为浮点数分配任何东西一样,我不应该期待任何东西作为回报。返回 NaN 是一种避免程序异常并让它完成它正在尝试做的事情的便捷方法,但如果您正在设计自己的方式来实现这一点,这将不那么令人惊讶。但这会带来其他问题,因为您必须捕获每个抛出的异常并以某种优雅的方式处理。

    案例2:只有调用hasFoo()才能区分真0和空0

    这肯定会令人惊讶,因为不是每个人都知道他们需要检查另一个值来验证它是否为实际 0,但您将在这里优雅地处理异常。

    【讨论】:

    • 一个问题是这种语言没有异常,所以对于案例 1,我们 panic() 不会被用户轻易“捕获”。我的库确实在线程级别捕获它并阻止它杀死整个程序,但通常这是一个错误条件,我倾向于支持它,因为调用 bar() 而不检查 hasBar() 是整数的程序员错误,它永远不可能是正确的做法。对于浮点数,你会得到 NaN,对于字符串“”等。这可能会也可能不会,但我宁愿它也恐慌以在类型之间保持一致。
    • 这两种不同的零业务令人惊讶,我不喜欢它。它会绊倒更多的程序员,而不仅仅是总是让它非法。
    【解决方案2】:

    如果 API 返回可空值,作为开发人员,如果语言支持,我最希望返回类型可以为空 (https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx)

    按照这些思路,如果您希望有很多空值作为常规用例,那么最好创建一个返回的包装器响应对象,类似于以下伪代码示例:

    public class Response<T>()
    {
        bool HasValue { get; }
        T Value { get; }
    }
    

    因此,使用这种方法,您将返回 Response 而不是 int 和 Response 而不是 float...等。

    【讨论】:

    • 它的界面差不多。您使用 foo().HasValue() 和 foo().Value() 而不仅仅是 foo() 和 hasFoo()。更糟糕的是,无论是外观还是性能。它与我的问题中的问题正交(如果 HasValue 为假,当您调用 Response.Value 时,您的示例中会发生什么?)
    • 不同的是,一旦我有了 Response 对象,API 就不再负责该对象的使用方式。如果我滥用响应对象,它会发生在我的代码中。如果 API 抛出异常,我认为是 API 开发者设计的不好。
    • 似乎更像是把它变成了别人的问题。据我所知,它并没有真正改善事情。
    • 另一个优点是,这允许调用者实现自己的异常或空处理。此外,这意味着 API 不必提供诸如 hasFoo() 之类的方法。
    • 如果HasValue 为假,您会得到一个异常,指出您在没有可用值时调用了Value,您应该在调用Value 之前先检查HasValue。你不能为不正确使用对象的人立法
    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    相关资源
    最近更新 更多