PMD 规则背后的“原因”
Posted
技术标签:
【中文标题】PMD 规则背后的“原因”【英文标题】:The "Why" behind PMD's rules 【发布时间】:2011-01-31 09:04:33 【问题描述】:是否有很好的资源来描述 PMD 规则集背后的“原因”? PMD's site 有“什么”——每条规则的作用——但它没有描述为什么 PMD 有这条规则,以及为什么忽略这条规则会给你在现实世界中带来麻烦。特别是,我很想知道为什么 PMD 有 AvoidInstantiatingObjectsInLoops 和 OnlyOneReturn 规则(如果您需要创建一个与集合中的每个对象对应的新对象,第一个似乎是必要的,第二个似乎在许多情况下是必要的根据某些标准返回一个值),但我真正想要的是一个链接,描述了大多数 ,因为这经常出现。
为了清楚起见,我知道我可以禁用这些以及如何做到这一点,我只是想知道为什么它们首先存在。抱歉,如果我错过了一些明显的东西,但在发布之前我做了谷歌搜索和 SO 搜索。我也明白这些问题通常是“品味”问题——我正在寻找的是规则的论据是什么以及有什么替代方案。举个具体的例子,你应该如何实现一个对象对应一个循环中的每个对象(这是Java中的常见操作)而不实例化循环中的每个对象?
【问题讨论】:
我相信您可能会喜欢 steve mcConnell 的《Code Complete》一书,他对这些问题的探讨更加清晰和详尽。 我去看看。这更符合我的要求。 【参考方案1】:在每种情况下,规则可以是特定情况的问题,也可以只是“品味”。
如果存在大量迭代并且实例化代价高昂,则应避免在循环中实例化对象。如果您可以将代码移出循环,您将避免许多对象实例化,从而提高性能。话虽如此,这并不总是可能的,在某些情况下,它对代码的整体性能并不重要。在这些情况下,以更清楚者为准。
对于 OnlyOneReturn,有多种方式来看待这一点(每种方式背后都有强烈的支持者),但它们基本上都归结为品味。
对于您的示例,OnlyOneReturn 支持者需要如下代码:
public int performAction(String input)
int result;
if (input.equals("bob"))
result = 1;
else
result = 2;
return result;
而不是:
public int performAction(String input)
if (input.equals("bob"))
return 1;
else
return 2;
如您所见,ReturnOnlyOnce 的额外清晰度值得商榷。
另请参阅与instantiation within loops 相关的这个 SO 问题。
【讨论】:
与 FindBugs 相比,+1 PMD 在大多数情况下不应该被认真对待。 最后一个样本无论如何都应该生成一个“不必要的 else 子句”警告 :) @matt b - 这也是品味问题。 :) 嗨,我有一个小问题。 “我应该信任并遵守 PMD 的规则吗?”。 为什么要链接到关于 php 的 SO 问题?我希望 PHP 和 Java 以完全不同的方式工作。【参考方案2】:这篇文章,A Comparison of Bug Finding Tools for Java,“由 Nick Rutar、Christian Almazan 和 Jeff Foster 撰写,比较了 Java 的几个错误检查器......”—FindBugs Documents and Publications。 PMD 看起来更加冗长。
附录:正如作者建议的那样,
"所有的工具选择不同的权衡 产生误报和漏报。”
特别是,AvoidInstantiatingObjectsInLoops 可能根本不是一个错误,如果这是意图的话。它包括帮助Avoid creating unnecessary objects。同样,OnlyOneReturn 本质上是暗示性的。多次返回表示 goto 的一种形式,有时是 considered harmful,但合理地用于提高可读性。
我最讨厌的是那些在不了解误报概念的情况下强制使用此类工具的人。
如 here 所述,PMD 的更新版本在集成到构建过程中时支持改进的自定义。
【讨论】:
有趣的论文,但不是我要问的。正如我上面所说,我知道我可以禁用这些警告,我想知道 PMD 提供这些警告背后的原因是什么。 啊,您特别想阐明这两条规则。我已经在上面详细说明了,但是@jsight 引用的答案特别好地解决了 OnlyOneReturn。 我从来没有真正想过 return 类似于 goto,这很有帮助。 我现在认为它们是理所当然的,但是一些有用的控制流机制可能被认为是结构化编程的“偏差”。 en.wikipedia.org/wiki/Structured_programming#Common_deviations AvoidInstantiatingObjectsInLoops 在许多常见情况下是不可避免的。例如,从结果集中填充 POJO 列表。【参考方案3】:您可以查看 PMD 主页,此处对规则进行了详细说明,并且通常带有原因。该网站是针对规则组构建的,这里是基本规则的链接:http://pmd.sourceforge.net/rules/basic.html
【讨论】:
正如我在帖子中所说,我知道这一点,这不是我要寻找的,因为大多数时候没有原因(特别是对于我正在寻找的两个)。【参考方案4】:每个规则都在 PMD 规则集中,它可以为您提供规则背后的推理线索(如果规则集页面本身没有详细解释)。
在 AvoidInstantiatingObjectsInLoops 的情况下,一次又一次地实例化类似的对象可能会很昂贵。然而,它经常是必要的。在我自己的项目中,我禁用了此规则,因为它标记了太多误报。
在 OnlyOneReturn 的情况下,请注意它位于名为 Controversial 的规则集中,这暗示这些规则是有争议的,并且取决于具体情况。我也禁用了整个规则集。
【讨论】:
是的,就像我说的,我知道你可以而且我经常这样做,禁用规则。以上是关于PMD 规则背后的“原因”的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Gradle > 2.0 中查找 PMD 规则集名称