23

Eclipseで自分のコードに対してPMDプラグインを実行しましたが、以下に示すようなコードに対して優先度の高い警告が表示されます。

 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

しかし、それでもコードへの影響を理解することはできません。誰かが例を挙げて私を案内してくれるなら、私はそれをいただければ幸いです。

4

9 に答える 9

33

多くの PMD ルールは、正確性に関する警告というよりもスタイルの意見です。このルールに同意しない場合、またはルールがプロジェクトのコーディング標準と一致しない場合は、警告を抑制したり、PMD を構成して好きなルールのみを適用したりすることを検討できます。

于 2012-11-06T19:07:24.040 に答える
13

PMDはツールです。PMDはヒューリスティックに基づいて機能します。誰かがこのヒューリスティックを決定しました。elseステートメントを使用した否定的な条件は「適切なスタイル」ではありません。

ただし、この場合、コメントで議論したように、投稿されたコードはがそれを書く方法です。(特に、x != nullこの構成に限定されません。)

これは、条件付き(単純化できる場合を除いて、たとえばJim Kinによって示される二重否定の削除)ではなく、分岐または「フロー」のロジックを確認するためです。

つまり、最初に正のブランチを配置します。この場合、私はそれを主張します

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が提案しているのと同様に-通常、正のブランチ/フローが反転された場合のブロックの上部でのアクションを示すコメントを付けます。

使用される条件付き選択に影響を与える可能性のある別の要因は、次のような「即時スコープ終了」ブランチです。

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
} 

これは私が 一貫して(いくつかの時折の例外は別として)私のコードを書く方法です:if (x != null) { .. }。利用可能なツールを使用します。そしてそれらをあなたのために働かせます。PMDをより適切な「味」に設定する方法については、Stevenの回答を参照してください。

于 2012-11-06T18:57:08.263 に答える
9

これは読みやすさの問題です。検討

if ( x != y ) 
{
}
else  // "if x doesn't not equal y"
{
}

対。

if ( x == y )
{
}
else  // "if x doesn't equal y"
{
}

後者の例は、よりすぐに識別できます。ネガを使用しても何も問題はありません...もっと理にかなっていると思います

if ( x != null )...
于 2012-11-06T18:44:35.550 に答える
4

私が負のケースの使用を避ける唯一の理由は、それが二重負になる場合であり、混乱を招く可能性があります。

例えば

if (!checkbox.disabled) {
    // checkbox is enabled
} 
else {
    // checkbox is disabled
}
于 2012-11-06T18:49:38.027 に答える
3

誰があなたのコードを読みますか? あなたがやる。コンパイラが行います。または、講師のアシスタントかもしれません。== と != の違いがわからない同僚?願っていません。

複雑な表現ではネガが悪いとしか思えません。(文脈:少なくとも私にとっては。頭の中でデバッグすることに不満を感じていることは知っていますwhile(!expr && !expr2 || expr3) { }

ch=getch(); if (ch!='a')
if (ch!='a' || ch!='b')は、意味的に正しいように聞こえながら、常に true に 簡単に拡張できるパターンです。

パフォーマンスの観点からは、確率を並べ替えるのが最善です。

if (more_probable) {
      ....
      unconditional_jump_to_end_of_block;
} else {
   ...
}

より可能性の高いブランチでは予測ミスのペナルティがないため、この選択はパフォーマンスの向上につながるはずです。

if (p && p->next)パフォーマンスの観点から評価すると、悪い結果が得られます。

于 2012-11-06T19:00:01.520 に答える
1

if 条件で「等しくない」を避ける必要があります。これは、他の誰かがあなたのコードを見たときに、その人が != を無視して、プログラムのロジックについて誤った結論に飛びつく可能性が現実にあるためです。

あなたの場合、ifロジックをelseロジックと交換し、!=を==に変更する必要があるかもしれません

于 2012-11-06T18:46:25.673 に答える
1

これは、コードの読みやすさとコード構成のバランスを取るケースです。この警告は基本的に、コードを読んで否定の否定をナビゲートするのは混乱を招くことを示唆しています。

私の個人的な経験則は、「通常の」ケースであると予想されるものは何でも、if でテストする必要があるということです。検討:

 if (x != y) {
   // do work here...
 } else {
   throw new IllegalArgumentException();
 }

この状況では、ケースで重要な作業が行われていると言えますx != y。そのため、それをテストする必要があります。これは、重要な作業が最初に来て、例外的なケースの処理が続くようにコードを整理するのが好きだからです。

于 2012-11-06T18:47:02.163 に答える
0

「良いスタイル」は、可能であればテストは「ポジティブ」であるべきだと言っているためです。

if (singleRequest == null){
   // do my other work
} else {
   // do my work
}

テストが「正」(つまり、「等しくない」ではなく「等しい」) であるため読みやすく、最終的に読みやすさが向上するとバグが少なくなります。

編集済み

これは特に次のようなテストに当てはまります。

if (!str.equals("foo")) {

先頭にある を簡単に見逃す可能性があり!ますが、テストをポジティブにすれば、はるかにクリーンになります。

否定的なテストを行う必要があるのは、ブロックがない場合だけです。その場合、スタイルの問題と見なされるelse空のブロックがない限り、否定的なテストは避けられません。true

于 2012-11-06T18:47:16.203 に答える
0

本当の答えではありませんが、全体的な複雑さを最小限に抑え、早期に戻るか失敗してからインデントなしで続行することで読みやすさを向上させることができます。

if (something == null) {
    throw new IllegalArgumentException("something must not be null");
}

// continue here
于 2017-08-22T07:59:18.297 に答える