ブール値のチェックにxor演算子を使用するのは良い習慣ですか?
-
03-07-2019 - |
質問
個人的には、 exclusive or 、 ^
の演算子は、その簡潔さのためにブールチェックのコンテキストで意味がある場合に好きです。書くのが好きです
if (boolean1 ^ boolean2)
{
//do it
}
より
if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}
しかし、初心者だけでなく、他の経験豊富なJava開発者から見た目が混乱していることがよくあります。
^
演算子の使用に関するベストプラクティスについて興味があります。
解決
代わりに!=
を使用できます。
他のヒント
あなたはあなた自身の質問に答えたと思います-人々から奇妙な外観を得るなら、より明確なオプションを使用する方がおそらく安全です。
コメントする必要がある場合は、おそらくより冗長なバージョンに置き換えて、そもそも人々に質問させない方がよいでしょう。
似たような会話をたくさんしていることがわかりました。一方で、目標を達成するためのコンパクトで効率的な方法があります。一方で、チームの他のメンバーが理解できないものがあり、将来の保守が難しくなります。
私の一般的なルールは、使用されているテクニックが一般的なプログラマーに知っておくのが妥当かどうかを尋ねることです。この場合、プログラマーにブール演算子の使用方法を知ってもらうのが妥当であると思うので、ifステートメントでxorを使用しても問題ありません。
大丈夫ではないものの例として、一時変数を使用せずにxorを使用して2つの変数を交換するトリックを取ります。これは、誰もが知っているとは思わないだろうトリックなので、コードレビューに合格しません。
コメントしていただければ大丈夫だと思います。 // ^ == XOR
。
いつでも関数にラップして、冗長な名前を付けることができます:
public static boolean XOR(boolean A, boolean B) {
return A ^ B;
}
しかし、^演算子が何のためにあるのかを知らなかった人にとっては、Googleにとってそれは本当に速いことです。初めてのことを覚えるのは難しくありません。他の用途を求めたので、ビットマスキングにXORを使用するのが一般的です。
XORを使用して、3番目の一時変数を使用せずに2つの変数の値を交換することもできます。
// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;
最近、職場のJavaScriptプロジェクトでxorを使用し、 7行のコメントを追加して、何が起こっているのかを説明しました。そのコンテキストでxorを使用する理由は、用語の1つ(以下の例では term1
)が2つではなく3つの値を取ることができるということでした: undefined
、 true
または false
で、もう一方( term2
)は true
または false
です。 undefined
の場合は追加のチェックを追加する必要がありますが、xorでは、最初の用語がブールとして最初に評価され、 undefined
は false
として扱われます:
if (term1 ^ term2) { ...
最終的には少しやり過ぎでしたが、とにかくイースターエッグのようにそこに残したかったです。
if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}
このコードは単純化できます:
if(boolean1 != boolean2)
{
//do it
}
コードの明確さを念頭に置いて、私の意見では、ブールチェックでXORを使用することは、XORビット演算子の一般的な使用法ではありません。私の経験から、Javaのビット単位のXORは、マスク flag toggle
の動作を実装するために通常使用されています:
flags = flags ^ MASK;
Vipan Singlaによるこの記事では、使用例について詳しく説明しています。
例のようにビット単位のXORを使用する必要がある場合は、ビット単位のリテラシーのある聴衆でさえトラックを止めて使用する理由を理解する必要があるため、使用する理由をコメントしてください。
使用パターンがそれを正当化するのであれば、なぜですか?あなたのチームはすぐにオペレータを認識しませんが、時間が経てば可能になります。人間は常に新しい言葉を学びます。プログラミングではなぜですか?
私が述べるかもしれない唯一の注意は、" ^" 2番目のブールチェックの短絡セマンティクスはありません。短絡セマンティクスが本当に必要な場合は、静的utilメソッドも機能します。
public static boolean xor(boolean a, boolean b) {
return (a && !b) || (b && !a);
}
個人的に" boolean1 ^ boolean2"を好む簡潔さによる表現。
私があなたの状況にあった場合(チームで働いている場合)、「boolean1 ^ boolean2」をカプセル化して妥協します。 " isDifferent(boolean1、boolean2)"などの説明的な名前を持つ関数のロジック。
たとえば、「boolean1 ^ boolean2」を使用する代わりに、「isDifferent(boolean1、boolean2)」を呼び出します。そのように:
if (isDifferent(boolean1, boolean2))
{
//do it
}
あなたの" isDifferent(boolean1、boolean2)"関数は次のようになります。
private boolean isDifferent(boolean1, boolean2)
{
return boolean1 ^ boolean2;
}
もちろん、このソリューションは、見かけ上無関係な関数呼び出しの使用を必要とし、それ自体がベストプラクティスの精査の対象となりますが、冗長な(およびandい)式"(boolean1&&!boolean2)| | (boolean2&&!boolean1)"!
!=は2つの変数を比較しても問題ありません。ただし、複数の比較では機能しません。
str.contains("!=") ^ str.startsWith("not(")
私には見た目が良い
str.contains("!=") != str.startsWith("not(")
ビット単位の演算子であるxorは、他の置換手段よりもはるかに高速です。したがって、パフォーマンスが重要でスケーラブルな計算を行うには、xorが不可欠です。
私の主観的な個人的意見:ブール値に等号(==または!=)を使用することは、いかなる目的でも絶対に禁止されています。これを使用すると、基本的なプログラミングの倫理と基礎が欠けていることがわかります。混乱したルックスを与えてくれる人は誰でもブール代数の基礎に送り返す必要があります(ここでは「信念の川に」と書きたいと思いました:))。