0

考虑一个名为 Graph 的类中的以下两个函数。完整的源代码可以在这里找到: http ://www.keithschwarz.com/interesting/code/?dir=dijkstra 。

public void addNode(T node) {
        mGraph.put(node, new HashMap<T, Double>());
    }

public void addEdge(T start, T dest, double length) {
        mGraph.get(start).put(dest, length);
    }

在这里,该方法是它添加到 mGraphaddEdge中的盲目信任方法。相信课堂上的其他方法正在正确地完成他们的工作,这是一种常见的做法吗?或者是否建议一种方法对一切都持怀疑态度并进行如下检查:addNodehashmap

 public void addEdge(T start, T dest, double length) {
            Map m = mGraph.get(start)
            if ( m ! = null)  ... ... 
        }

再一次,我有兴趣知道 whatscommonly done和 whats ideally recommended

4

8 回答 8

3

这种调试是开发过程的一部分,不应成为运行时的问题。

方法不信任其他方法。他们都信任你。这就是发展的过程。修复所有错误。然后方法不必“信任”。毫无疑问。

所以,写它应该是。不要让方法检查其他方法是否正常工作。这应该由开发人员在编写该函数时进行测试。如果您怀疑某个方法没有执行您想要的操作,请对其进行调试。

于 2013-12-31T23:55:24.583 回答
1

我不知道我是否理解这个问题,但我认为你可以抛出一个 Exceptionget方法。请参阅此示例ArrayList

ArrayList<Integer> a = new ArrayList<Integer>();
a.get(1); # Index 1

这会引发异常:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
...

get()所以在你的情况下,你可以在你的方法中抛出一个异常:

public void T get(int i) {
     ...
    if (... == null)
        throw new Exception("No value found.");
}

并在addEdge()方法中:

public void addEdge(T start, T dest, double length) {
    try {
        mGraph.get(start).put(dest, length);
    } catch(Exception exc) {
        System.out.println("Error: " + exc.getMessage());
    }
}
于 2014-01-01T00:03:08.457 回答
0

我的 2 美分。

这是一个加载的问题恕我直言。我习惯的一个经验法则是看看这个函数将如何被调用。如果调用者是我可以控制的,那么可以假设它将使用正确的参数和正确的初始化来调用它。

另一方面,如果它的某个客户端我无法控制,那么进行彻底的错误检查是个好主意。

于 2013-12-31T23:53:56.230 回答
0

addEdge 信任的不仅仅是 addNode 方法的更正。它还相信 addNode 方法已被其他方法调用。我建议包括检查 m 是否不为空。

于 2013-12-31T23:54:26.453 回答
0

通常这是不好的做法。由于可以在 addNode 之前调用 addEdge 并抛出 NullPointerException (NPE),因此 addEdge 应检查结果是否为 null 并抛出更具描述性的异常。在我看来,唯一可以接受不检查空值的情况是当您期望结果永远不会为空时,在这种情况下,NPE 具有足够的描述性。

于 2013-12-31T23:54:40.020 回答
0

这就是构造函数发挥作用的地方。如果你有一个总是创建一个新 Map 的默认构造函数(例如,没有参数),那么你确定这个类的每个实例总是有一个已经实例化的 Map。

于 2013-12-31T23:54:52.220 回答
0

如果它在同一个类中,则可以信任该方法。

这样做很常见。最好检查构造函数和方法的参数中的空值,以确保没有人将空值传递给它们(如果不允许)。然后,如果您以一种从未将“开始”图设置为空的方式实现您的方法,请不要在那里检查空值。

为您的方法实施单元测试并确保它们被正确实施也是一种很好的做法,因此您可以信任它们。

于 2013-12-31T23:55:27.960 回答
0

我认为您“正确”的概念有点值得商榷。您的示例似乎表明返回null不正确。null一种方法在返回并以某种方式迫使您考虑这种可能性时可能是非常正确的。

一个编写良好的方法将非常清楚地定义该方法可能的输入域和输出范围(返回类型、特定情况下的异常null空对象等)。还应该有一套测试来传达如何调用该方法以及如何考虑所有这些可能性。

在现实世界中,特别是如果您与来自其他组织的开发人员的项目可能不太自律,那么您可能就没有那么幸运了。防御性编程很好,但我相信您作为客户必须确保您不做任何掩盖违反其合同的方法中的错误的事情。异常在开发中是一件好事;当某处出现问题时,不要害怕让他们通知您。然后可以让开发人员意识到他们的代码需要加强以满足其合同。

最后,由于问题中的一个标签特别提到了Effective Java ... null,因此您应该测试并记录当客户端使用--like throwing调用您的方法时您将做什么。在你的私有方法中,做一个你的先决条件,这样你就得到了s。nullIllegalArgumentExceptionassertAssertionError

于 2014-01-01T00:01:08.460 回答