if ('константа' == $ змінна) проти якщо ($ змінна == 'константа')


49

Останнім часом я багато працював у PHP та конкретно в рамках WordPress. Я помічаю багато коду у вигляді:

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

Де я б очікував побачити:

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

Чи є ця конвенція знайдена в певних мовах / рамках? Чи є причина, що колишній підхід є кращим для другого (з точки зору обробки, з точки зору розбору чи навіть з точки зору людини?)

Або це просто питання смаку? Я завжди вважав, що краще, виконуючи тест, щоб мінливий елемент, який тестується на якусь константу, знаходиться зліва. Здається, краще відобразити те, як ми б задали питання природною мовою: "якщо торт шоколадний", а не "якщо шоколад - торт".


1
Я ніколи не пишу такий код, але щоб бути справедливим, "якщо шоколад - аромат торта", це звучить природно. Природна мова більш гнучка.
Рік Сладкі

4
@Rick Це може здатися природним мовою, але ви не можете заперечити, що коли ви бачите такий код, вам потрібно зупинитися спочатку (можливо, лише на секунду), щоб подумати, що це робиться.
Едгар Гонсалес

4
@Edgar Gonzalez: Погодився, я твердо проти цього в коді.
Rick Sladkey

3
Розділ 19 Повного коду 2-го видання (у розділі "Булеві вирази: загальні проблеми з булевими виразами") фактично рекомендує цю практику з точної причини, зазначеної у багатьох відповідях тут: щоб запобігти призначенню в мовах, похідних С, коли порівнювалося порівняння .
CraigTP

4
Я часто бачив, як вони називаються "Умовами Йоди"
Брайан

Відповіді:


84

Основна причина цього (так званий "Yoda conditional") - запобігання нещасних випадків, коли ви випадково використовуєте оператор присвоєння ( =) замість оператора рівного порівняння ( ==).

Тобто, якщо ви зробили помилку:

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

Заява оцінюватиметься true(або, у випадку деяких мов (наприклад, PHP) - трибунове значення), і ви будете мати важко знайти помилку.

Але якщо ви зробили це:

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

Ви отримаєте фатальну помилку, оскільки не можете призначити $fooціле число.

Але, як ви зазначали, зміна порядку в цілому робить речі менш читабельними. Отже, багато стандартів кодування (але не всі, включаючи WordPress ) пропонують або вимагають, $foo == 1незважаючи на переваги полювання на помилок 1 == $foo.

Як правило, моя порада - дотримуватися будь-якого встановленого стандарту кодування, якщо він існує: для WordPress це означає використовувати умовні умови Yoda.

Коли немає, і неможливо встановити консенсус з однолітками, це вибір дилера.


2
Я пам'ятаю, коли розробляв мову (давно), що ми спеціально зробили :=оператора присвоєння ( ==для тесту на рівність), щоб уникнути подібних проблем.
Стипендіати доналу

7
Я написав багато, багато рядків коду, і я ніколи не випадково набирав =замість цього ==. Різниця настільки наголошена скрізь, що я просто ніколи їх не плутав. З іншого боку, я прочитав багато фрагментів коду, які заплутані або інакше важко зрозуміти. Як такий, я б поставив пріоритети на читабельність :). Незалежно, хороша відповідь.
crazy2be

5
Ще одна вагома причина використовувати -Wall -Werrorабо еквівалент вашого компілятора / інтерпретатора. Є дуже мало ситуацій, коли призначення в умові є правильним, не кажучи вже про легше. Багато мов цього навіть не дозволяють.
Карл Білефельдт

7
Педантичний: хоча if($foo = 1)оцінюється на trueдеяких мовах, у PHP він оцінює до 1; if($foo = 20)оцінює до 20; if($foo = 0)оцінює до 0, що на відміну від інших є помилковим. Це може додати цілий «нижній шар складності для помилки.
Чарльз

2
Насправді Стандарти кодування WordPress ВЗАЄМО
Том

13

Це захисний механізм кодування, який покликаний запобігти випадковому використанню оператора призначення.

Розглянемо неправильне використання / помилку оператора присвоєння замість оператора рівності

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

Наведені вище умови завжди повертають би істину, але це, мабуть, не те, що мав на увазі оригінальний програміст. Поміркуйте, на своєму місці це

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

Тут PHP (і більшість інших мов) відмовляться від запуску, оскільки неможливо присвоїти нічого фіксованому значенню 1. Кодуючи таким чином всі умовні висловлювання, ви автоматично забезпечуєте випадкове використання оператора присвоєння в умовному режимі.


9

Мені подобається використовувати цю конвенцію в java, щоб видалити можливість виключення нульового вказівника. Тож щось подібне не викличе у вас жодних проблем і не потребуватиме додаткового коду:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}

3
Мені це подобається, але я ненавиджу загальну ідіому.
Томас Едінг

3
Якщо нульове значення не є дійсним для цього пункту коду, ви все одно повинні були перевірити його чи все-таки створили ваш код таким чином, що нульове значення було б неможливим.
Ред С.

6
це здається простим способом маскування проблем. Пил не очищають, затискаючи їх всередину килима.
Лежати Райан

0

На практиці багато компіляторів подадуть вам попередження, якщо ви напишете "if (x = 1)" замість "if (x == 1)", оскільки це, швидше за все, помилка.

За допомогою Clang ви можете уникнути попередження, ефективно сказавши компілятору "Я маю на увазі це, і я знаю, що я роблю", і це робиться, написавши "if ((x = 1))". Зверніть увагу на додаткові дужки. Це працює і в інших ситуаціях. якщо (помилкове) твердження; може надати вам попередження про те, що заява ніколи не виконується; if ((false)) твердження; не дає цього попередження.


Мені це дуже подобається! Я уникаю наступних, повністю легітимних ідіом у PHP, тому що я завжди отримую попередження у своєму IDE:if ($array = getSomething()){ // ..so something with $array }
Том Оже,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.