我面临着一个奇怪的情况。我实际上是第一次尝试Junit测试。多年来,我一直教导过静态方法不好(在某些情况下(。
但是
我发现在课堂内有一些私人静态方法真的很不错。主要原因是我可以控制进入内部的所有方法:我确定我只能控制和更改参数。
任何例子都是微不足道的,实际上,这只是一种" 防止自己在错误情况下对错误对象做错事的方法",也许是因为我忘记了一个对象必须是从一开始到执行方法的结尾相同。喜欢封装。
所以,我正在解释让我这样思考的最后情况:
class Graph {
private Set<Edge> edges;
// {...}
public void newEdge(Edge e) {
edges.add(e);
edges = simplify(edges);
}
private static Set<Edge> simplify(Set<Edge> input) {
// do something
return output;
}
}
不是这样:
private static Set<Edge> simplify(Set<Edge> input) {
// do something
return output;
}
比
更安全private void simplify(Set<Edge> input) {
// do something
this.edges = output;
}
?
请告诉我我是否生气。非常感谢
并不是说静态方法不好,只是它们具有特定的目的。
首先,我们正在谈论一种私人方法,因此班级以外的任何代码都不常见。因此,只有班级的开发人员才能编写代码来调用它。这意味着它不太可能被错误地称为。
另外,您对班级的测试也应验证其应有的方式。
其次,静态方法无法访问对象内的实例变量。因此,如果该方法的目的是从实例变量中读取或修改实例,则不能是静态的。
如果该方法执行的计算在变量的内部突变中是常见的,并且希望为外部呼叫者执行相同服务的公共静态方法,则该方法应该是静态的。但是,如果不是这样,就不需要静态。
编辑:例如:
如果您不需要执行简化:
class Graph {
private Set<Edge> edges;
// {...}
public void newEdge(Edge e) {
edges.add(e);
simplify();
}
private void simplify() {
// use this.edges as your input
// do something
// set the value of your output to this.edges
}
}
另一个编辑:
一个对象必须从执行方法
的执行结束到末端相同。
如果多线程环境中的一致性对您来说是一个问题,则需要使用适当的线程同步方法 - 不要仅依赖于方法末尾修改对象。
在我的评论中进一步构建,正如@Jason所述,静态方法还不错,只是在某些情况下它们更适合。例如,暴露一块自我包含的功能通常是将静态方法与众不同的原因。
这意味着您需要自己提供参数,例如simplify
方法。这并不能真正扩展,如果您有一个Graph
对象,那么simplify
行为将是对象暴露的东西。
这是依赖注入,因为这将使您的测试更容易构建。因此,在您的情况下,您将拥有类似的东西:
class Graph {
private Set<Edge> edges;
public Graph(Set<Edge> edges) {
this.edges = ...
}
}
上面的某些内容允许您创建一个模拟边缘列表,然后使用它来执行您的测试。