代码分析器:PMD和FindBugs

7

1. 关于PMD:

1.1 如何设置PMD检查,以忽略一些警告,例如“变量名太短或太长”,“删除空构造函数”等等。如果这样做,会出现另一个警告,说类必须有一些静态方法。基本上,该类是空的,为了后续开发,我想暂时保持它为空。

1.2 是否需要遵循这个警告建议?

  A class which only has private constructors should be final

1.3 这是什么意思?

 The class 'Dog' has a Cyclomatic Complexity of 3 (Highest = 17)

1.4 这个怎么办?我很想改变它,但目前还没有任何关于改变的想法。

Assigning an Object to null is a code smell. Consider refactoring.

2.关于FindBugs:

2.1 在静态字段声明后的某个时刻写入它真的很糟糕吗?以下代码会给我一个警告:

Main.appCalendar = Calendar.getInstance();
Main.appCalendar.setTimeInMillis(System.currentTimeMillis());

其中appCalendar是一个静态变量。

2.2 这段代码:

strLine = objBRdr.readLine().trim();

显示警告:

Immediate dereference of the result of readLine()

其中objBRdr是一个BufferedReader(FileReader)。可能会发生什么情况?readLine()可能为null吗? 该代码嵌套在while (objBRdr.ready())测试中,到目前为止,我在那里没有任何问题。

更新1:当我用以下代码替换原来的代码时,2.2被修复了:

strLine = objBRdr.readLine();
    if (strLine != null) {
        strLine = strLine.trim();
    }

嗯...我能说什么呢?我是一个好奇的人类 :-). 感谢提供链接。 - hypercube
2个回答

9

1.1如何设置PMD检查?

PMD将规则配置存储在称为Ruleset XML文件的特殊存储库中。此配置文件包含有关当前安装的规则及其属性的信息。

这些文件位于PMD发行版的rulesets目录中。在使用Eclipse时,请参考Customizing PMD

1.2 Is it necessary to follow this warning advice?

A class which only has private constructors should be final
所有构造函数始终以调用超类构造函数开始。如果构造函数显式包含对超类构造函数的调用,则使用该构造函数。否则,隐含使用无参数构造函数。如果无参数构造函数不存在或对子类不可见,则会出现编译时错误。
因此,实际上不可能从每个构造函数都是私有的类派生子类。将这样的类标记为final是一个好主意(但不是必要的),因为它明确防止子类化。

1.3 What is that supposed to mean?

The class 'Dog' has a Cyclomatic Complexity of 3 (Highest = 17)
复杂度是方法中决策点的数量加上方法入口一个。决策点包括'if'、'while'、'for'和'case标签'。一般来说,1-4表示低复杂度,5-7表示中等复杂度,8-10表示高复杂度,11+表示非常高的复杂度。
话虽如此,我只会引用聚合环形复杂度毫无意义的一些部分:

[...] This metric only has meaning in the context of a single method. Mentioning that a class has a Cyclomatic complexity of X is essentially useless.

Because Cyclomatic complexity measures pathing in a method, every method has at least a Cyclomatic complexity of 1, right? So, the following getter method has a CCN value of 1:

public Account getAccount(){
   return this.account;
}

It’s clear from this boogie method that account is a property of this class. Now imagine that this class has 15 properties and follows the typical getter/setter paradigm for each property and those are the only methods available. That means the class has 30 simple methods, each with a Cyclomatic complexity value of 1. The aggregate value of the class is then 30.

Does this value have any meaning, man? Of course, watching it over time may yield something interesting; however, on its own, as an aggregate value, it is essentially meaningless. 30 for the class means nothing, 30 for a method means something though.

The next time you find yourself reading a copasetic aggregate Cyclomatic complexity value for a class, make sure you understand how many methods the class contains. If the aggregate Cyclomatic complexity value of a class is 200– it shouldn’t raise any red flags until you know the count of methods. What’s more, if you find that the method count is low yet the Cyclomatic complexity value is high, you will almost always find the complexity localized to a method. Right on!

所以对我来说,这个PMD规则应该小心处理(实际上并不是很有价值)。

1.4 What about this one? I would love to change this, but nothing crosses my mind at the moment regarding the change:

Assigning an Object to null is a code smell. Consider refactoring.

不确定你对这个的疑惑在哪里。

2.1 延迟至静态字段声明之后再写入,真的那么糟糕吗?[...]

我猜测你会收到警告,是因为该方法包含非同步的懒加载非易失性静态字段。由于编译器或处理器可能重新排序指令,如果该方法可以被多个线程调用,则不能保证线程看到一个完全初始化的对象。您可以使字段易失性以解决问题。

2.2 [...] readLine() 的结果立即解除引用

如果没有更多文本行可读,则 readLine() 将返回 null,并且解除引用将生成空指针异常。因此,确实需要检查结果是否为 null。


谢谢,伙计!一如既往的精彩反馈。虽然“圈复杂度”听起来有点可怕,但现在并没有那么糟糕 :-)。我期待着阅读您对这个回答的下一个编辑,而且看起来它是迄今为止最佳响应的主要候选人。实际上,我已经发现PMD和FindBugs插件都具有UI可选择的警告检查..问这个问题是我的错。 - hypercube
好的..请编译并编辑您的回答,这样我就可以选择它作为最佳答案了 :-). 谢谢。 - hypercube
现在看起来只有1.4和2.1需要回答了 :-D。 - hypercube
所以,您在文本中添加了3个字符:-)。好的,这仍然是最佳答案。谢谢! - hypercube
不用客气。关于您的额外询问,我建议您创建另一个问题。 - Pascal Thivent
显示剩余4条评论

2

以下是需要翻译的内容:

1.4 为什么要将对象赋值为null?如果您重用同一变量,则没有必要在此之前将其设置为null。

2.1 这个警告的原因是为了确保类Main的所有实例都具有相同的静态字段。在您的Main类中,您可以使用static Calendar appCalendar = Calendar.getInstance() ;

对于您的2.2,您是正确的,通过null检查,您可以确保不会出现任何NullPointerException。我们永远不知道您的BufferedReader何时可能会阻止/损坏,这种情况并不经常发生(据我所知),但我们永远不知道硬盘何时会崩溃。


我正在使用类似于Dog instance = null的东西,在某些事件上强制一些可视化组件重新绘制。 - hypercube
你对圈复杂度的定义是错误的。一个方法的圈复杂度是指该方法独立路径的数量。请参阅http://en.wikipedia.org/wiki/Cyclomatic_complexity。 - Pascal Thivent
啊..又是脚本 :-). 这对我来说是个教训,要验证答案。我也会验证你的 :-P。谢谢。 - hypercube
我的错,你是对的Pascal Thivent。我会编辑我的答案,以免让人们感到困惑。 - Nettogrof
是的,又是那个脚本!我还在观察着你 :) - Pascal Thivent
Heeeee :-). 我很高兴听到这个 :-). - hypercube

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接