Java 通常应在何时或为什么使用状态检查功能?

Java 通常应在何时或为什么使用状态检查功能?,java,api,design-patterns,Java,Api,Design Patterns,假设我们有一个API interface Graph { boolean checkIfPathExists(source, destination); List<Integer> getPath(source, destination); } 选项2:不强制执行功能顺序。如果调用了getPath,则让getPath()在内部调用checkIfPathExists(),如果checkIfPathExists()返回false,则返回空集合 Graph g = new

假设我们有一个API

interface Graph {
    boolean checkIfPathExists(source, destination);
    List<Integer> getPath(source, destination);
}
选项2:不强制执行功能顺序。如果调用了getPath,则让getPath()在内部调用checkIfPathExists(),如果checkIfPathExists()返回false,则返回空集合

Graph g = new GraphImpl(graph);
List path = g.getPath(s, d);
在我看来,Option2对我来说很好,但我唯一的问题是对“状态检查方法”的冗余/不必要的调用,如“checkIfPathExists()”。理想情况下,getPath()不应该这样做。它应该只是返回路径

  • 哪一个是更好的实现选项1或选项2


  • 如果option2是一个更好的选项,那么根本不添加“checkIfPathExists”作为公共接口会是一个更好的设计选择吗?要使问题更通用,状态检查方法如“hasNext()”所示,如果不强制执行,则不必要。即使迭代列表,我们也可以得到列表的大小并使用for循环,直到我不知道这是什么类型的API,但我不认为两个顶点之间不存在路径是一种例外情况,所以抛出和异常似乎不是一个好主意

    如果您正在争取一个新的目标,那么您可以删除
    布尔checkIfPathExists(源、目标)并使用Guava的类作为
    getPath(源、目标)的返回值指示两个顶点之间可能不存在路径。请记住,您必须区分不存在的路径和零长度路径

    另一方面,如果您想提供一个示例,那么您可以保持
    布尔checkIfPathExists(源、目标)
    是一种方便的方法,用于检查到顶点之间是否存在路径,而不强制客户端实际检索路径(这甚至可能为性能优化提供一些空间)。请注意,这只是一个方便的方法,在
    getPath
    之前调用它不是强制性的,我认为这甚至不是一个好的设计,因为它会导致错误

    最后,如果您不能决定哪一个更好,那么请坚持使用最小API,这样以后更容易扩展。记住约书亚·布洛赫的金科玉律:

    如有疑问,请将其排除在外


    是否有一个
    checkIfExists
    hasNext
    函数,该函数的存在只是为了“保护”对另一个函数的调用,这实际上取决于受保护函数的成本和结果

    如果
    getPath
    非常昂贵,并且
    checkIfPathExists
    非常快,那么将这两个函数同时使用是有意义的。但是,在
    getPath
    之前,对相同参数强制调用
    checkIfPathExists
    ,这是不寻常的,而且似乎是不必要的,因为如果可以将该机制放入,则还可以缓存其结果,因此不需要在
    getPath
    中实际强制执行,只要使用缓存(如果可用)或执行调用即可

    对于使用
    hasNext
    迭代器
    ,部分原因是调用
    next
    会产生后果和未知成本(可能是使用网络连接将从数组到单链接列表的任何内容进行迭代)。一旦调用了
    next
    ,您也无法返回,因此在处理当前元素的逻辑根据是否存在下一个元素而变化的情况下,迭代器需要支持它

    如果您特别担心性能,那么您可以提供两种方法,一种方法假设路径确实存在(
    checkIfPathExists
    已被调用并返回true),因此不需要执行存在性检查,另一种方法不作此假设,在搜索之前将调用
    checkIfPathExists
    。在javadoc中适当地记录这些方法,用户通常会正确地使用它们


    要直接回答您的问题,通常首选选项2,因为它更符合预期,并且不需要额外的代码复杂性来验证调用序列。说明先调用
    checkIfPathExists
    的好处(如果存在)的文档足以解决此选项的任何问题。

    我同意您的看法。我认为没有必要对“checkIfPathExists()”进行额外的函数调用。说api不能修改有什么意义?它要么与你的问题无关,要么使你的问题毫无意义。
    Graph g = new GraphImpl(graph);
    List path = g.getPath(s, d);