函数应该多少信任另一个函数

时间:2013-12-31 23:48:19

标签: java verification effective-java

在名为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);
    }

此处,addEdge方法盲目信任addNode方法,已将hashmap添加到mGraph。通常的做法是相信课堂上的其他方法正确地正常工作吗?或者是否建议某种方法对所有内容持怀疑态度并进行检查:

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

再一次,我有兴趣知道什么是commonly done和什么ideally recommended

8 个答案:

答案 0 :(得分:3)

此类调试是开发过程的一部分,不应该是运行时的问题。

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

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

答案 1 :(得分:1)

我不知道我是否理解了这个问题,但我认为你可以抛出异常get方法。请参阅此示例并使用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());
    }
}

答案 2 :(得分:0)

我的2美分。

这是一个加载的问题imho。我使用的经验法则是看看如何调用此函数。如果调用者是我可以控制的东西,那么可以假设它将使用正确的参数和正确的初始化进行调用。

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

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

一个编写良好的方法将非常清楚地定义输入的域和输出范围(返回类型,在某些情况下的例外,null,一个null object等)。方法。还应该有一套测试来传达如何调用方法以及如何解释所有这些可能性。

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

最后,由于问题中的一个标签特别提到了{em> Effective Java ... ... null的主题,你应该测试并记录你在做什么时会做什么客户端使用null调用您的方法 - 例如抛出IllegalArgumentException。在私有方法中,执行assert前提条件,以便获得AssertionError s。