if („stała” == zmienna) vs. if ($ zmienna == „stała”)

49

Ostatnio dużo pracuję w PHP, a konkretnie w ramach WordPress. Zauważam dużo kodu w postaci:

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

Gdzie spodziewałbym się zobaczyć:

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

Czy jest to konwencja stosowana w niektórych językach / ramach? Czy jest jakiś powód, dla którego to pierwsze podejście jest lepsze niż drugie (z perspektywy przetwarzania, perspektywy analizy, a nawet perspektywy ludzkiej?)

Czy to tylko kwestia gustu? Zawsze uważałem, że lepiej podczas wykonywania testu, że zmienna pozycja testowana względem jakiejś stałej znajduje się po lewej stronie. Wydaje się, że lepiej odwzorowuje sposób, w jaki zadalibyśmy pytanie w języku naturalnym: „jeśli ciasto jest czekoladą”, a nie „jeśli czekolada jest ciastem”.

Tom Auger
źródło
1
Nigdy nie piszę takiego kodu, ale szczerze mówiąc „jeśli czekolada to smak ciasta”, brzmi naturalnie. Język naturalny jest bardziej elastyczny.
Rick Sladkey
4
@Rick Może to zabrzmieć naturalnie w języku, ale nie można zaprzeczyć, że kiedy widzisz taki kod, musisz najpierw przestać (może tylko na sekundę), aby pomyśleć, co on chce zrobić.
Edgar Gonzalez,
4
@Edgar Gonzalez: Zgadzam się, jestem zdecydowanie przeciwny kodowaniu.
Rick Sladkey
3
Rozdział 19 kodu Complete 2nd Edition (w sekcji „Wyrażenia boolowskie: typowe problemy z wyrażeniami boolowskimi”) tak naprawdę zaleca tę praktykę z dokładnego powodu podanego w wielu odpowiedziach tutaj: aby uniknąć przypisania w językach pochodnych C, gdy chodziło o porównanie .
CraigTP
4
Często widziałem te określane jako „Warunki Yoda”
Brian

Odpowiedzi:

84

Głównym powodem tego (tak zwane „warunkowe Yoda”) jest zapobieganie wypadkom, w wyniku których przypadkowo używasz operatora przypisania ( =) zamiast operatora równego porównania ( ==).

To znaczy, jeśli popełniłeś błąd, robiąc:

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

Oświadczenie będzie oceniać na true(lub, w przypadku niektórych języków - jak PHP - prawdziwa wartość), a będziesz miał trudny do znalezienia błąd.

Ale jeśli zrobiłeś:

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

Otrzymasz błąd krytyczny, ponieważ nie możesz przypisać $fooliczby całkowitej.

Ale, jak zauważyłeś, odwrócenie kolejności zazwyczaj sprawia, że ​​rzeczy są mniej czytelne. Tak więc wiele standardów kodowania (ale nie wszystkie, w tym WordPress ) sugeruje lub wymaga, $foo == 1pomimo zalet polowania na błędy 1 == $foo.

Ogólnie rzecz biorąc, radzę postępować zgodnie z ustalonym standardem kodowania, o ile istnieje: w przypadku WordPress oznacza to używanie warunkowych programów Yoda.

Jeśli nie ma, a niemożliwe jest ustanowienie jednego poprzez konsensus z rówieśnikami, wybór dealera.

Attila
źródło
2
Pamiętam, kiedy projektowałem język (dawno temu), który specjalnie stworzyliśmy :=operatorem przypisania (z ==testem równości), aby uniknąć tego rodzaju problemów.
Donal Fellows
7
Napisałem wiele, wiele linii kodu i nigdy nie napisałem przypadkowo =zamiast ==. Różnica jest tak wyraźna wszędzie, że nigdy ich nie myliłem. Z drugiej strony przeczytałem wiele fragmentów kodu, które są mylące lub trudne do zrozumienia. Jako takie postawiłbym priorytety na czytelność :). Niezależnie od tego dobra odpowiedź.
crazy2be
5
Kolejny dobry powód do użycia -Wall -Werrorlub odpowiednik twojego kompilatora / tłumacza. Istnieje bardzo niewiele sytuacji, w których przypisanie w ramach warunku jest poprawne, a tym bardziej bardziej czytelne. Wiele języków nawet na to nie pozwala.
Karl Bielefeldt
7
Pedantyczny: Podczas gdy if($foo = 1)ocenia truew niektórych językach, w PHP zmienia się na 1; if($foo = 20)ocenia do 20; if($foo = 0)ocenia na 0, co w przeciwieństwie do innych jest fałszem. Może to dodać do błędu całą „kolejną warstwę złożoności”.
Charles
2
W rzeczywistości Standardy kodowania WordPress Wzywają Yoda Conditionals: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger
13

Jest to defensywny mechanizm kodowania, który zapobiega przypadkowemu użyciu operatora przypisania.

Rozważ niewłaściwe użycie / błąd operatora przypisania zamiast operatora równości

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

Powyższy warunek zawsze zwróci prawdę, ale prawdopodobnie nie to miał na myśli oryginalny programista. Zastanów się, na swoim miejscu, to

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

Tutaj PHP (i większość innych języków) odmówiłoby uruchomienia, ponieważ niemożliwe jest przypisanie czegokolwiek do stałej wartości 1. Kodując w ten sposób wszystkie instrukcje warunkowe, automatycznie zabezpieczasz przed przypadkowym użyciem operatora przypisania w warunkach warunkowych.

Alan Storm
źródło
9

Lubię używać tej konwencji w Javie, aby usunąć możliwość wyjątku zerowego wskaźnika. Więc coś takiego nie spowoduje żadnych problemów ani nie będzie wymagało dodatkowego kodu:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
Ben Newman
źródło
3
Lubię to, ale nienawidzę ogólnego idiomu.
Thomas Eding
3
Jeśli wartość null nie jest ważna w tym punkcie kodu, powinieneś już ją sprawdzić lub zaprojektować kod w taki sposób, aby wartość null była niemożliwa.
Ed S.
6
wydaje się to łatwym sposobem maskowania problemów. Pyłów nie usuwa się, wzruszając nimi w dywanie.
Lie Ryan,
0

W praktyce wiele kompilatorów wyświetli ostrzeżenie, jeśli napiszesz „if (x = 1)” zamiast „if (x == 1)”, ponieważ najprawdopodobniej jest to błąd.

Dzięki Clang możesz uniknąć ostrzeżenia, skutecznie informując kompilator: „Mam na myśli to i wiem, co robię”, a dzieje się to przez napisanie „if ((x = 1))”. Zwróć uwagę na dodatkowe nawiasy. Działa to również w innych sytuacjach. instrukcja if (false); może ostrzec, że instrukcja nigdy nie zostanie wykonana; instrukcja if ((false)); nie daje tego ostrzeżenia.

gnasher729
źródło
Bardzo to lubię! Unikam następującego, całkowicie poprawnego idiomu w PHP, ponieważ zawsze otrzymuję ostrzeżenia w moim IDE:if ($array = getSomething()){ // ..so something with $array }
Tom Auger