if ('constant' == $ variable) vs. if ($ variable == 'constant')

48

In letzter Zeit habe ich viel in PHP und speziell im WordPress-Framework gearbeitet. Ich bemerke viel Code in Form von:

if ( 1 == $options['postlink'] )

Wo hätte ich erwartet zu sehen:

if ( $options['postlink'] == 1 )

Ist dies eine Konvention, die in bestimmten Sprachen / Frameworks zu finden ist? Gibt es einen Grund, warum der erstere Ansatz dem letzteren vorzuziehen ist (aus Sicht der Verarbeitung, der Analyse oder sogar aus Sicht des Menschen?)

Oder ist es nur Geschmackssache? Ich habe es mir immer besser vorgestellt, wenn ich einen Test durchführe, dass das variable Element, das gegen eine Konstante getestet wird, auf der linken Seite ist. Es scheint besser zu sein, wie wir die Frage in natürlicher Sprache stellen würden: "Wenn der Kuchen Schokolade ist" anstatt "Wenn Schokolade der Kuchen ist".

Tom Auger
quelle
1
Ich schreibe niemals Code wie diesen, aber um fair zu sein: "Wenn Schokolade das Aroma des Kuchens ist", klingt das natürlich. Natürliche Sprache ist flexibler.
Rick Sladkey
4
@Rick Es mag in der Sprache natürlich klingen, aber Sie können nicht leugnen, dass Sie, wenn Sie Code wie diesen sehen, zuerst anhalten müssen (vielleicht nur für eine Sekunde), um zu überlegen, was es ist, was es zu tun versucht.
Edgar Gonzalez
4
@Edgar Gonzalez: Einverstanden bin ich fest dagegen im Code.
Rick Sladkey
3
Kapitel 19 von Code Complete 2nd Edition (im Abschnitt "Boolesche Ausdrücke: Häufige Probleme mit Booleschen Ausdrücken") empfiehlt diese Vorgehensweise aus dem genauen Grund, der in vielen der hier aufgeführten Antworten angegeben ist: Um die Zuweisung in C-abgeleiteten Sprachen zu verhindern, wenn ein Vergleich beabsichtigt war .
CraigTP
4
Ich habe oft gesehen, dass diese als "Yoda-Bedingungen" bezeichnet werden
Brian

Antworten:

83

Der Hauptgrund dafür (so genannte "Yoda-Bedingung") ist die Vermeidung von Unfällen, bei denen Sie versehentlich einen Zuweisungsoperator ( =) anstelle des Vergleichsoperators "Gleich" ( ==) verwenden.

Das heißt, wenn Sie den Fehler gemacht haben:

$foo = 5;
if ($foo = 1) {
  // Stuff
}

Die Anweisung wird zu true(oder im Fall einiger Sprachen - wie PHP - zu einem Wahrheitswert) ausgewertet, und es wird ein schwer zu findender Fehler auftreten.

Aber wenn du getan hast:

$foo = 5;
if (1 = $foo) {
  // Stuff
}

Sie erhalten einen schwerwiegenden Fehler, weil Sie keine $fooGanzzahl zuweisen können .

Aber wie Sie bereits betont haben, ist es im Allgemeinen weniger lesbar, wenn Sie die Reihenfolge umkehren. Daher empfehlen oder erfordern viele Codierungsstandards (aber nicht alle, einschließlich WordPress ) $foo == 1trotz der Fehlerbehebung die Vorteile von 1 == $foo.

Im Allgemeinen rate ich dazu, den etablierten Codierungsstandard zu befolgen, sofern es einen gibt: Für WordPress bedeutet dies, Yoda-Bedingungen zu verwenden.

Wenn dies nicht der Fall ist und es unmöglich ist, im Konsens mit Ihren Kollegen einen solchen zu finden, hat der Händler die Wahl.

Attila
quelle
2
Ich erinnere mich, dass wir beim Entwerfen einer Sprache (vor langer Zeit) speziell :=den Zuweisungsoperator (mit ==Gleichheitstest) festgelegt haben, um diese Art von Problemen zu vermeiden.
Donal Fellows
7
Ich habe viele, viele, Codezeilen geschrieben, und ich habe nie versehentlich getippt =statt ==. Der Unterschied ist überall so ausgeprägt, dass ich sie nie verwirrt habe. Andererseits habe ich viele Code-Teile gelesen, die verwirrend oder auf andere Weise schwer zu verstehen sind. Als solches würde ich die Schwerpunkte auf die Lesbarkeit legen :). Egal, gute Antwort.
crazy2be
5
Noch ein guter Grund -Wall -Werroroder das Äquivalent Ihres Compilers / Interpreters. Es gibt sehr wenige Situationen, in denen eine Zuordnung innerhalb einer Bedingung korrekt ist, geschweige denn besser lesbar. Viele Sprachen erlauben es nicht einmal.
Karl Bielefeldt
7
Pedantisch: Während in einigen Sprachen if($foo = 1)ausgewertet truewird, wird in PHP stattdessen 1 ausgewertet. if($foo = 20)ergibt 20; if($foo = 0)ergibt 0, was im Gegensatz zu den anderen falsch ist. Dies kann den Fehler um eine ganze Ebene komplexer machen.
Charles
2
Tatsächlich fordern die WordPress-Codierungsstandards Yoda-Bedingungen: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger
13

Es ist ein defensiver Codierungsmechanismus, der eine versehentliche Verwendung des Zuweisungsoperators verhindern soll.

Betrachten Sie einen Missbrauch / Fehler des Zuweisungsoperators anstelle des Gleichheitsoperators

if ( $options['postlink'] = 1  )

Die obige Bedingung würde immer true zurückgeben, aber das ist wahrscheinlich nicht das, was der ursprüngliche Programmierer im Sinn hatte. Betrachten Sie, an seiner Stelle, dies

if( 1 = $options['postlink'])

Hier würde PHP (und die meisten anderen Sprachen) die Ausführung verweigern, da es unmöglich ist , dem festen Wert von etwas zuzuweisen 1. Indem Sie alle bedingten Anweisungen auf diese Weise codieren, stellen Sie automatisch sicher, dass ein Zuweisungsoperator nicht versehentlich in einer Bedingung verwendet wird.

Alan Storm
quelle
9

Ich verwende diese Konvention gerne in Java, um die Möglichkeit einer Nullzeiger-Ausnahme zu beseitigen. So etwas verursacht keine Probleme oder benötigt keinen zusätzlichen Code:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
Ben Newman
quelle
3
Ich mag das, aber ich hasse die allgemeine Sprache.
Thomas Eding
3
Wenn ein Nullwert bis zu diesem Punkt im Code nicht gültig ist, sollten Sie ihn ohnehin bereits überprüft oder Ihren Code so entworfen haben, dass ein Nullwert unmöglich wäre.
Ed S.
6
Dies scheint eine einfache Möglichkeit zu sein, Probleme zu maskieren. Staub wird nicht durch Achselzucken im Teppich gereinigt.
Lie Ryan
0

In der Praxis erhalten Sie von vielen Compilern eine Warnung, wenn Sie "if (x = 1)" anstelle von "if (x == 1)" eingeben, da dies höchstwahrscheinlich ein Fehler ist.

Mit Clang können Sie die Warnung umgehen, indem Sie dem Compiler effektiv mitteilen, "Ich meine es ernst, und ich weiß, was ich tue". Dazu schreiben Sie "if ((x = 1))". Beachten Sie die zusätzlichen Klammern. Das funktioniert auch in anderen Situationen. if (falsche) Aussage; kann Sie warnen, dass die Anweisung niemals ausgeführt wird; if ((false)) Anweisung; gibt diese Warnung nicht.

gnasher729
quelle
Ich mag das sehr! Ich vermeide die folgenden, völlig legitimen Redewendungen in PHP, da ich in meiner IDE immer Warnungen erhalte:if ($array = getSomething()){ // ..so something with $array }
Tom Auger