如何记录Java方法的(简单)前提条件?

时间:2014-11-03 22:54:39

标签: java javadoc

通常情况下,方法对其参数施加约束,而类型系统无法对其进行描述。例如,方法可能要求某些参数为非null,或者某些int类型的参数为正数。可能还存在更复杂的前提条件,例如之前调用某个方法,或者某个对象处于某种状态。在Javadoc中记录这个的最佳方法是什么?

例如,假设我有以下公共库函数,其中参数不能为负数:

public void foo(int bar) {
    if (bar < 0) {
        throw new IllegalArgumentException("Negative bars cannot be food.");
    }
    ...
} 

我希望以这样的方式记录这一点,使其从文档文本的其余部分“脱颖而出”,以便文档读者立即知道他们必须查看的位置。目前,我通过向Javadoc添加throws子句来执行此操作:

/**
 * Foos a bar.
 * @param bar  the bar to be food
 * @throws IllegalArgumentException  if bar is negative
 */
public void foo(int bar) {
    ...

然而,这引入了将异常抛出到方法的规范中。现在,库用户可能在其代码中依赖于此行为。因此,如果我想以允许负参数的方式更改下一版本中的方法,我可能会破坏客户端的代码。

在Javadoc中记录这样的事情是否有最佳实践?我想到了:

  • 在文档文本中描述如果参数为负,则该方法具有未定义的行为。但是,这并没有真正脱颖而出,因此许多图书馆用户可能会错过它。
  • 使用注释(public void foo(@NonNegative int bar))。但是,为此,标准的注释集将是理想的,并且此标准集似乎不存在。

2 个答案:

答案 0 :(得分:5)

您似乎对依靠API的Javadocs提供的信息犹豫不决:您的API文档。虽然我同意一些开发人员总是会忽略它的警告,但我认为历史上Javadocs已经完全足以提供有关如何正确使用API​​的充分指导。您可以疯狂地创建各种自定义Annotation,但最终人们仍会错误地实施您的API。

如果你确实想要进一步超越你已经拥有的东西,那么你也可以在任何可行的地方实现self-documenting命名约定。例如:

/**
 * Foos a positive bar.
 * @param positiveBar  the non-zero,non-negative bar to be food
 * @throws IllegalArgumentException  if bar is zero or negative
 */
public void foo(int positiveBar) {
    ...

最后,虽然你的问题是关于如何记录这些约束而不是处理它们,但我会说不要低估IllegalArgumentException的价值。这正是应该使用的,工程师不应该害怕抛出此异常来指示编程错误。当开发人员的实施没有完成时,开发人员不会在没有阅读文档的情况下走得更远。

答案 1 :(得分:1)

您可以为条件, inv ariant创建custom javadoc tags,即@pre @inv@post 发表条件。

此外,Joshua Bloch在Effective Java Second Edition中提出论点:

  

doc注释应该枚举所有方法的前提条件,这些是为了让客户端调用它而必须为true的东西,以及它的 postconditions 通常,先决条件由@throws代码隐式描述,用于未经检查的异常;每个未经检查的异常对应于前提条件违规。此外,可以在@param标记中指定前置条件以及受影响的参数。

示例:

  

@param索引返回的元素索引;必须是非负的和更少的   比这个列表的大小@throws IndexOutOfBoundsException如果   index超出范围({@code index&lt; 0 || index&gt; = this.size()})

请注意,每个例外都以 if 开头,后跟一个描述抛出异常的条件的子句。 (前提条件)这通常用算术表达式来描述。