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.