我在Eclipse中运行了PMD plugin对我的代码,我得到了一个高优先级警告,代码类似于下面所示的代码:
if(singleRequest !=null){
// do my work
}else{
// do my other work
}
PMD说`Avoid if (x != y) ..; else ..
;
错误的描述如下:
In an "if" expression with an "else" clause, avoid negation in
the test. For example, rephrase:
if (x != y) diff(); else same();
as:
if (x == y) same(); else diff();
Most "if (x != y)" cases without an "else" are often return
但我仍然无法理解对我的代码的影响。如果有人可以用一个例子来指导我,我将不胜感激。
答案 0 :(得分:32)
许多PMD规则比正确性警报更具风格意见。如果您不同意此规则或该规则与您项目的编码标准不符,您可以考虑suppressing warnings甚至configuring PMD to enforce only the rules you like
答案 1 :(得分:13)
PMD是一种工具。 PMD基于启发式工作。有人决定使用这种启发式方法;带有else语句的负面条件不是“好风格”。
但是,在这种情况下,正如我在评论中提到的那样,发布的代码是我将如何写。 (特别是x != null
,但不仅限于此构造。)
这是因为我不看条件(除非它可以简化;例如删除Jim Kin所示的双阴影),而是我看看<的逻辑em>分支或“流”。
也就是说,我首先放置正分支。在这种情况下,我认为
if (x != null) {
doValid // positive branch
} else {
doFallback
}
在语义上等同于
if (isValid(x)) { // it looks like a "positive conditional" now
doValid // still positive branch
} else {
doFallback
}
因此首先是正分支。
当然,并非所有情况都有这种“明确”的正向流动,并且某些表达方式可能以消极的方式表达得更容易。在这些情况下,我将“反转”分支 - 类似于PMD建议的 - 通常用一条注释来说明如果正的分支 / flow被反转则在块顶部的动作。
可能影响所使用的条件选择的另一个因素是“即时范围退出”分支,如:
if (x == null) {
// return, break, or
throw new Exception("oops!");
} else {
// But in this case, the else is silly
// and should be removed for clarity (IMOHO) which,
// if done, avoids the PMD warning entirely
}
我 一致(除了一些偶然的例外)写我的代码:{{1 }}。使用可用的工具;让他们为你工作。请参阅Steven关于如何在这里将PMD配置为更合适的“品味”的答案。
答案 2 :(得分:8)
这是一个可读性问题。考虑
if ( x != y )
{
}
else // "if x doesn't not equal y"
{
}
VS
if ( x == y )
{
}
else // "if x doesn't equal y"
{
}
后一个例子可以立即识别出来。请注意,我认为使用底片并没有错...它可以更有意义,考虑
if ( x != null )...
答案 3 :(得分:4)
我避免使用否定案例的唯一原因是,如果它导致双重否定,这可能会令人困惑。
e.g。
if (!checkbox.disabled) {
// checkbox is enabled
}
else {
// checkbox is disabled
}
答案 4 :(得分:3)
谁读你的代码?你做。编译器。或者也许是讲师的助手。一个同事,谁也无法区分==和!=?希望不是。
我只能认为复杂表达中的负面效果不好。 (背景是:至少对我而言。我知道我在调试中感到沮丧while(!expr && !expr2 || expr3) { }
)
ch=getch(); if (ch!='a')
是一种很容易扩展到的模式
if (ch!='a' || ch!='b')
这总是正确的,而听起来在语义上是正确的。
从性能角度来看,最好对概率进行排序。
if (more_probable) {
....
unconditional_jump_to_end_of_block;
} else {
...
}
这种选择应该会带来更好的表现,因为在更可能的分支中没有错误的预测惩罚。
从绩效角度评估的 if (p && p->next)
会产生不良结果。
答案 5 :(得分:1)
你必须避免在if条件下“不等于”。这是因为当其他人查看你的代码时,这个人很可能会忽略!=并且可能会错误地得出关于你的程序逻辑的结论。
对于您的情况,您可能必须将if逻辑与else逻辑互换并更改!= to ==
答案 6 :(得分:1)
这是代码可读性与代码组织的平衡案例。这个警告基本上表明,阅读代码的人在导致否定否定时会感到困惑。
我个人的经验法则是,无论你期望什么是“正常”的情况,你应该在if中测试。考虑:
if (x != y) {
// do work here...
} else {
throw new IllegalArgumentException();
}
在这种情况下,我会说在x != y
案例中正在完成重要的工作,所以这就是你应该测试的。这是因为我喜欢组织代码,以便首先执行重要的工作,然后处理特殊情况。
答案 7 :(得分:0)
这是因为“好的风格”说如果可能的测试应该是“积极的”,那么:
if (singleRequest == null){
// do my other work
} else {
// do my work
}
更容易阅读,因为测试是“积极的”(即“等于”而非“不等于”),最终更好的可读性导致更少的错误。
特别是测试的情况如下:
if (!str.equals("foo")) {
你很容易错过前面的!
,但是如果你让测试结果为正,那就更清洁了。
你应该进行负面测试的唯一时间是没有else
阻止 - 那么除非你有一个空true
块,否则负面测试是不可避免的,这本身就被认为是一个样式问题。< / p>
答案 8 :(得分:0)
不是真正的答案,但您可以通过提前返回或失败然后继续而不缩进来最小化整体复杂性并提高可读性:
if (something == null) {
throw new IllegalArgumentException("something must not be null");
}
// continue here