假设我们有一个 API。
interface Graph {
boolean checkIfPathExists(source, destination);
List<Integer> getPath(source, destination);
}
以下哪一项是最佳/推荐的实现。
选项 1:强制检查以验证路径是否存在。如果之前没有调用 checkPath 则抛出异常。
Graph g = new GraphImpl(graph);
if (g.checkIfPathExists(s, d)) {
List path = g.getPath(s, d);
}
选项 2:不强制执行函数顺序。如果调用了 getPath,则让 getPath() 内部调用 checkIfPathExists(),如果 checkIfPathExists() 返回 false,则返回空集合;
Graph g = new GraphImpl(graph);
List path = g.getPath(s, d);
在我看来,选项2对我来说看起来不错,但我唯一的问题是对“状态检查方法(如“checkIfPathExists()”)的冗余/不必要的调用。理想情况下,这不是 getPath() 应该做的。它应该只是返回路径。
选项 1 和选项 2 哪个是更好的实现?
如果选项 2 是一个更好的选择,那么根本不添加“checkIfPathExists”作为公共(public)接口(interface)是否会是一个更好的设计选择?为了使问题更通用,状态检查方法看起来像“hasNext()”,如果不强制执行,则显得不必要。即使要迭代列表,我们也可以获取列表的大小并使用 for 循环直到 i <= size,并且根本不使用 hasNext()。 简而言之,如果不强制执行状态检查功能,它们有什么用?
有任何强制执行状态检查方法的“现实生活”示例吗?意思是,不先调用它们会导致异常吗?
最佳答案
我不知道这是什么API,但我不认为两个顶点之间不存在路径是一种异常(exception)情况,所以抛出异常似乎不太好想法。
如果您正在努力争取 minimal interface那么你可以删除 boolean checkIfPathExists(source, destination);
从您的 API 并使用 Guava 的 Optional类作为返回值 getPath(source, destination);
指示两个顶点之间可能不存在路径。请记住,您必须区分不存在的路径和零长度路径。
另一方面,如果您想提供human interface那么你可以保留boolean checkIfPathExists(source, destination);
作为检查顶点之间是否存在路径的便捷方法,而不强制客户端实际检索它(这甚至可能为性能优化提供一些空间)。请注意,这只是一个方便方法,并不强制在getPath
之前调用它。我认为这甚至不是一个好的设计,因为它会导致 sequential coupling .
最后,如果您无法决定哪个更好,那么坚持使用最少的 API,以后更容易扩展。请记住 Joshua Bloch 的黄金法则:
When in doubt leave it out
关于java - 通常应何时或为何使用状态检查函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18282014/