Ist es schlecht, explizit mit booleschen Konstanten zu vergleichen, z. B. wenn (b == false) in Java?

73

Ist es schlecht zu schreiben:

if (b == false) //...

while (b != true) //...

Ist es immer besser stattdessen zu schreiben:

if (!b) //...

while (!b) //...

Vermutlich gibt es keinen Unterschied in der Leistung (oder gibt es?), Aber wie bewerten Sie die Aussagekraft, die Prägnanz, die Klarheit, die Lesbarkeit usw. zwischen den beiden?

Aktualisieren

Um die Subjektivität einzuschränken, würde ich mich auch über Zitate aus Richtlinien für maßgebliche Codierungsstile freuen, die immer vorzuziehen sind oder wann verwendet werden sollen.


Hinweis : Der Variablenname bwird nur als Beispiel verwendet, ala foound bar.

Polygenschmierstoffe
quelle
9
Ich persönlich mag den Vergleich mit einem Literal aus Gründen der Lesbarkeit - bei hohen Auflösungen (und zunehmendem Alter) wird der Ausruf von vielen Buchstaben "absorbiert".
Uri
@Uri: Eine ausreichend gute IDE sollte in der Lage sein !, so viel hervorzuheben, wie Sie möchten, wenn dies wirklich ein Problem ist.
Polygenelubricants
55
if (b == false == true == true) {Du willst sicher sein.
Tom Hawtin - Tackline
2
@Triynko, normalerweise wird so etwas optimiert, so dass es keine Rolle spielt, und wenn es nicht so ist, wird es keinen merklichen Unterschied verursachen.
Nacht
8
Die Wahrheit ist, dass die Leute nur "== true" und dergleichen verwenden, weil sie nicht wirklich darüber nachgedacht haben, und wenn sie darauf hingewiesen werden, behaupten sie "Lesbarkeit", um das Gesicht zu retten.
Nacht

Antworten:

67

Es ist nicht unbedingt schlecht, es ist nur überflüssig. Auch der tatsächliche Variablenname hat viel Gewicht. Ich würde zum Beispiel if (userIsAllowedToLogin)oben if (b)oder noch schlimmer bevorzugen if (flag).

Das Leistungsproblem wird vom Compiler in keiner Weise optimiert.

Update : In Bezug auf die maßgeblichen Quellen kann ich in den Sun Coding Conventions nichts explizit finden , aber zumindest hat Checkstyle ein SimplifyBooleanExpressionModul, das davor warnt.

BalusC
quelle
7
+1 für die Empfehlung langer, beschreibender Variablennamen. Ich denke jedoch, dass "if (userIsAllowedToLogin ())" "if (userIsAllowedToLogin () == true)" vorzuziehen ist, da ersteres besser lesbar ist.
Michael Aaron Safyan
@ Michael, hast du ein vergessen !?
Thorbjørn Ravn Andersen
Ich würde es vorziehen if( canAuthenticate() )oder if( isAuthorized() ). Ich finde userIsAllowedToLoginmehrdeutig. Bedeutet dies, dass der Benutzer die Anmeldeseite anzeigen kann (z. B. die IP-Adresse ist nicht gesperrt), oder bedeutet dies, dass der Benutzer authentifiziert wurde (z. B. korrekter Name und Passwort)?
Dave Jarvis
1
@ Dave: Es war nur ein etwas übertriebenes Beispiel. Solange der Variablenname selbsterklärend genug ist.
BalusC
4
@ BalusC: Ich weiß; Es ist ein Haustier Ärger. Lange Methodennamen - wie isCurrentUserLoggedInAsRole- sind manchmal ein Symptom für ein größeres Problem: eine falsch platzierte Methode. (Zum Beispiel sollte die UserKlasse ihre zugewiesenen Rollen kennen : user.isAssigned( role ).)
Dave Jarvis
48

Sie sollten nicht den ersten Stil verwenden. Ich habe gesehen, wie Leute Folgendes benutzten:

  • if ( b == true )
  • if ( b == false )

Ich persönlich finde es schwer zu lesen, aber es ist passabel. Ein großes Problem, das ich mit diesem Stil habe, ist jedoch, dass es zu den unglaublich kontraintuitiven Beispielen führt, die Sie gezeigt haben:

  • if ( b != true )
  • if ( b != false )

Dies erfordert vom Leser mehr Aufwand, um die Absicht des Autors zu bestimmen. Persönlich finde ich einen expliziten Vergleich mit wahr oder falsch überflüssig und damit schwerer zu lesen, aber das bin ich.

Thomas
quelle
8
+1 Dies ist eine weitere beste Antwort in diesem Thema. Sie sind in der Tat (ein bisschen) schwerer schnell zu interpretieren . Zumindest für mich.
BalusC
35

Dies ist stark Geschmackssache.

Persönlich habe ich festgestellt, dass dies if (!a) {viel weniger lesbar ist (BEARBEITEN: für mich) als if (a == false) {und daher fehleranfälliger, wenn der Code später gepflegt wird, und ich habe konvertiert, um das letztere Formular zu verwenden.

Grundsätzlich mag ich die Auswahl von Symbolen für logische Operationen anstelle von Wörtern nicht (C gegen Pascal), weil für mich das a = 10 and not b = 20 Lesen einfacher ist als a == 10 && !(b==20), aber so ist es in Java.

Jeder, der den Ansatz "== false" zugunsten von "!" Offensichtlich hatte ich nie zu lange auf Code gestarrt und dieses Ausrufezeichen übersehen. Ja, Sie können Code-blind werden.

Thorbjørn Ravn Andersen
quelle
3
Ich stimme zu, auch ich bevorzuge es, == false im Vergleich zu (!) Aus Sicht der Lesbarkeit zu verwenden - wenn Sie den Code anderer Leute beibehalten, wie Sie sagen, ist Codeblindheit eine Sache und passiert. Wenn (K) {} oder wenn (! K) {} manchmal kann man ewig herausfinden, warum etwas nicht funktioniert, dann finde das! in dem Zustand.
Harag
Der beste Weg, dies zu lösen, besteht darin, den booleschen Ausdruckstest für wahr anstelle von falsch durchführen zu lassen und die Wenn-Dann-Blöcke entsprechend zu ordnen. Dies kann seltsam aussehen, wenn der wahre Block leer ist.
Thorbjørn Ravn Andersen
25

Der Hauptgrund, warum Sie den ersten Stil nicht verwenden sollten, ist, dass beide gültig sind:

if (b = false) //...

while (b = true) //...

Das heißt, wenn Sie versehentlich ein Zeichen weglassen, erstellen Sie eine Zuordnung anstelle eines Vergleichs. Ein Zuweisungsausdruck wertet den zugewiesenen Wert aus, daher weist die erste obige Anweisung den Wert falsezu bund wertet ihn aus false. Der zweite Abtretungsempfänger truezu b, so dass es immer auswertet true, egal , was Sie mit zu tun bin der Schleife.

Alan Moore
quelle
8
Ich würde nicht "übergeordneten" Grund sagen. Sofern Sie nicht vor 15 Jahren mit der Zeit gereist sind, wird Ihr Compiler vor diesem Tippfehler warnen.
John Kugelman
1
John meinte wahrscheinlich deine IDE. Beachten Sie, dass dies in C # ... jab nicht gültig ist!
Stephen Swensen
1
Ja, IDEs und Stilprüfer werden Sie vor solchen Dingen warnen. Es würde mich nicht wundern, wenn der Befehlszeilen-Compiler dies ebenfalls erkennen kann, obwohl er Sie standardmäßig nicht warnt. Mein Punkt ist, dass dies nicht nur eine Stilwahl ist.
Alan Moore
3
@StephenSwensen ist in C # gültig, generiert jedoch eine Warnung. Assignment in conditional expression is always constant; did you mean to use == instead of = ?
user247702
2
Eine einfache Möglichkeit, dies zu verhindern, besteht darin, stattdessen den konstanten Wert (lhs) mit der Variablen (rhs) zu vergleichen. Also while (true == loggedIn). Auf diese Weise wird eher ein Fehler zur Kompilierungszeit als zur Laufzeit ausgegeben.
Adam Brinded
11

Ersteres habe ich nie gesehen, außer in Code, der von Anfängern geschrieben wurde. es ist immer das letztere, und ich glaube nicht, dass irgendjemand wirklich verwirrt ist. Auf der anderen Seite denke ich

int x;
...
if(x) //...

vs.

if(x != 0) //...

ist viel umstrittener, und in diesem Fall bevorzuge ich die zweite

Michael Mrozek
quelle
4
@Michael, Java konvertiert int nicht implizit wie in C ++ in boolesche Werte, stimmt aber ansonsten zu 100% zu. Ersteres ist eine schlampige Newbie-Syntax, und Letzteres wird bevorzugt.
Michael Aaron Safyan
4
Oh, ich wusste nicht einmal, dass wir über Java sprachen :)
Michael Mrozek
1
es war in den Tags, aber jetzt auch im Titel erwähnt. Entschuldigen Sie das Durcheinander.
Polygenelubricants
1
Nun wissen Sie dank dieses Beitrags, dass einige erfahrene Programmierer "== false" schreiben - nicht nur "Anfänger", und Sie können ihre Gründe dafür klar lesen, wie in den Antworten hier mehrfach angegeben. (Hmmm ... war das ein unbewusstes Ad-Hominem? "Ich mag das, und die einzigen Leute, die ich jemals gesehen habe, die meiner Präferenz nicht zustimmen, sind nur 'Anfänger'.")
M.Bearden
@ M.Bearden Ernsthaft? Alles, was ich sagte, war, dass ich persönlich fast nie erfahrene Programmierer gesehen habe, die direkt mit trueoder verglichen wurden false, während ich es als TA am College die ganze Zeit von Anfängern sah, die einfach nicht erkannten, dass es überflüssig war. Das bedeutet nicht, dass Sie ein schlechter Mensch sind, es ist nur ungewöhnlich. Sie haben eine zufällige Bemerkung von vor fünf Jahren, die sich an niemanden richtete, ziemlich beleidigt. Schreiben Sie Code, wie Sie möchten
Michael Mrozek
7

IMHO, ich denke, wenn Sie nur die Bool-Variablennamen voranstellen "Is", wird dies selbstverständlich und aussagekräftiger, und dann können Sie den expliziten Vergleich mit trueoder entfernenfalse

Beispiel:

isEdited  // use IsEdited in case of property names
isAuthorized // use IsAuthorized in case of property names

etc

Mahesh Velaga
quelle
2
Die Konvention ist isEditednicht IsEdited(letzteres wäre eine Klasse)
Thorbjørn Ravn Andersen
6

Ich bevorzuge das erste, weil es klarer ist. Die Maschine kann entweder gleich gut lesen, aber ich versuche , Code zu schreiben , für andere Menschen zu lesen, nicht nur die Maschine.

Head Geek
quelle
Interessant, dass so viele Leute mit mir nicht einverstanden zu sein scheinen - diese Antwort hat derzeit sechs positive und drei negative Stimmen. Vielleicht erklärt das alle "Ball of Mud" -Projekte, die ich zur Bergung gerufen habe ...
Head Geek
3

Ich ziehe den langen Ansatz, aber ich vergleiche mit ==anstelle von !=99% der Zeit.

Ich weiß, dass es sich bei dieser Frage um Java handelt, aber ich C#wechsle oft zwischen Sprachen, und zum Beispiel kann ein Vergleich mit (für isntance) == falsehilfreich sein, wenn es um nullfähige Bool- Typen geht. Also habe ich die Gewohnheit, mit dem Operator zu vergleichen trueoder ihn zu falsebenutzen ==.

Ich mache diese:

if(isSomething == false) oder if(isSomething == true)

aber ich hasse diese:

if(isSomething != false) oder if(isSomething != true)

aus offensichtlichen Gründen der Lesbarkeit!

Solange Sie Ihren Code lesbar halten, spielt dies keine Rolle.

Joel
quelle
2

Persönlich würde ich den Code umgestalten, damit ich keinen negativen Test verwende. zum Beispiel.

if (b == false) {
   // false
} else {
   // true
}

oder

boolean b = false;
while(b == false) {
  if (condition)
      b = true;
}

IMHO, In 90% der Fälle kann Code überarbeitet werden, sodass der negative Test nicht erforderlich ist.

Peter Lawrey
quelle
aber nimm es nicht zu weit. Ob Sie es glauben oder nicht, ich habe bereits Code wie diesen gesehen: if (a); sonst doSomething ();
Axel
In diesem Fall würde ich es vorziehen, wenn (! A) etwas tun würde (); Es ist jedoch wahrscheinlich, dass Sie den Code so ändern können, dass 'b' true anstelle von false und false anstelle von true speichert und keine Negation erforderlich ist. IMHO ist es ziemlich selten, dass Sie brauchen, wenn (a) an einem Ort und wenn (! A) in einem nicht verwandten Codeblock.
Peter Lawrey
1

Meiner Meinung nach ist es einfach nervig. Nicht etwas, worüber ich einen Aufruhr verursachen würde.

ChaosPandion
quelle
1

Die normale Richtlinie ist, niemals gegen Boolesche Werte zu testen. Einige argumentieren, dass die zusätzliche Ausführlichkeit zur Klarheit beiträgt. Der hinzugefügte Code kann einigen Leuten helfen, aber jeder Leser muss mehr Code lesen.

Heute Morgen habe ich eine halbe Stunde verloren, um einen Fehler zu finden. Der Code war

    if ( !strcmp(runway_in_use,"CLOSED") == IPAS_FALSE)
      printf(" ACTIVE    FALSE \n");   else
      printf(" ACTIVE    TRUE \n");

Wenn es mit normaler Konvention codiert worden wäre, hätte ich viel schneller gesehen, dass es falsch war:

    if (strcmp(runway_in_use, "CLOSED"))
      printf(" ACTIVE    FALSE \n");   else
      printf(" ACTIVE    TRUE \n");
BOC
quelle
Ich denke, es gibt größere Lesbarkeitsprobleme in diesem Code als die Bedingung. Schau dir strcmp an. Nicht gerade mühelose IMO.
Preza8
1

Dies ist meine erste Antwort auf StackOverflow, also sei nett ... Vor kurzem habe ich beim Refactoring festgestellt, dass 2 Codeblöcke fast genau den gleichen Code hatten, aber einer verwendet hatte

for (Alert alert : alerts) {
    Long currentId = alert.getUserId();

    if (vipList.contains(currentId)) {
        customersToNotify.add(alert);

        if (customersToNotify.size() == maxAlerts) {
            break;
        }
    }
}

und der andere hatte

for (Alert alert : alerts) {
    Long currentId = alert.getUserId();

    if (!vipList.contains(currentId)) {
        customersToNotify.add(alert);

        if (customersToNotify.size() == maxAlerts) {
            break;
        }
    }
}

In diesem Fall war es also sinnvoll, eine Methode zu erstellen, die für beide Bedingungen wie diese funktioniert, indem boolean == conditiondie Bedeutung umgedreht wird

private void appendCustomersToNotify(List<Alert> alerts
        List<Alert> customersToNotify, List<Long> vipList, boolean vip){

    for (Alert alert : alerts) {
        Long currentId = alertItem.getUserId();

        if (vip == vipList.contains(currentId)) {
            customersToNotify.add(alertItem);

            if (customersToNotify.size() == maxAlerts) {
                break;
            }
        }
    }
}
lebenswichtig
quelle
0

Ich würde sagen, es ist schlecht.

while (!b) {
    // do something 
}

liest sich viel besser als

while (b != true) {
    // do something 
}
fastcodejava
quelle
0

Einer der Gründe, warum der erste (b == false) verpönt ist, ist, dass Anfänger oft nicht erkennen, dass die zweite Alternative (! B) überhaupt möglich ist. Die Verwendung der ersten Form kann also auf ein Missverständnis mit booleschen Ausdrücken und booleschen Variablen hinweisen. Auf diese Weise ist die Verwendung der zweiten Form zu einer Art Sjiboleth geworden: Wenn jemand dies schreibt, versteht er / sie wahrscheinlich, was los ist.

Ich glaube, dass dies dazu geführt hat, dass der Unterschied als wichtiger angesehen wird als er wirklich ist.

Kees Huizing
quelle
0

Während beide gültig sind, fühlt sich der erste für mich wie ein Tippfehler an.

Für mich b == falsesieht das genauso falsch aus wie (i == 0) == false. Es ist wie: huh?

Boolesche Werte sind keine Aufzählung mit 2 möglichen Werten. Sie vergleichen sie nicht. Boolesche Werte sind Prädikate und repräsentieren eine Wahrheit. Sie haben ganz bestimmte Operatoren wie &, |, ^, !.

Um die Wahrheit eines Ausdrucks umzukehren, verwenden Sie den Operator '!' Und sprechen Sie ihn als "nicht" aus.

Bei richtiger Benennung wird es natürlich: !isEmptyliest "nicht ist leer", für mich gut lesbar.
Während isEmpty == falseliest sich etwas wie "es ist falsch, dass es leer ist", was ich mehr Zeit brauche, um zu verarbeiten.

Florian F.
quelle