if ('constant' == $ variable) против if ($ variable == 'constant')

49

В последнее время я много работал над PHP и, в частности, в рамках WordPress. Я замечаю много кода в виде:

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

Где бы я ожидал увидеть:

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

Это соглашение встречается в определенных языках / структурах? Есть ли какая-либо причина, по которой первый подход предпочтительнее второго (с точки зрения обработки, или анализа, или даже с точки зрения человека?)

Или это просто вопрос вкуса? Я всегда думал, что лучше при выполнении теста, чтобы переменный элемент, проверяемый по некоторой константе, был слева. Кажется, это лучше соответствует тому, как мы задаем вопрос на естественном языке: «если торт - шоколад», а не «если шоколад - торт».

Том Оже
источник
1
Я никогда не пишу подобный код, но, честно говоря, «если шоколад - это вкус пирога», звучит естественно. Естественный язык более гибкий.
Рик Слэдки
4
@Rick Это может звучать естественно на языке, но вы не можете отрицать, что, когда вы видите такой код, вы должны сначала остановиться (возможно, только на секунду), чтобы подумать, что он пытается сделать.
Эдгар Гонсалес
4
@ Эдгар Гонсалес: Согласен, я категорически против этого в коде.
Рик Слэдки
3
Глава 19 Code Complete 2-е издание (в разделе «Булевые выражения: типичные проблемы с булевыми выражениями») фактически рекомендует эту практику по точной причине, изложенной во многих ответах здесь: для предотвращения присвоения в производных от C языках, когда подразумевается сравнение ,
CraigTP
4
Я часто видел, что они упоминаются как «Условия Йоды»
Брайан

Ответы:

84

Основная причина сделать это (так называемое «условие Йоды») состоит в том, чтобы предотвратить несчастные случаи, когда вы случайно используете оператор присваивания ( =) вместо оператора сравнения ( ==).

То есть, если вы допустили ошибку, сделав:

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

Оператор оценивает true(или, в случае некоторых языков, например, PHP, истинное значение), и у вас будет трудно найти ошибку.

Но если вы сделали:

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

Вы получите фатальную ошибку, потому что не можете присвоить $fooцелое число.

Но, как вы указали, изменение порядка обычно делает вещи менее читабельными. Таким образом, многие стандарты кодирования (но не все, включая WordPress ) предлагают или требуют, $foo == 1несмотря на преимущества поиска ошибок 1 == $foo.

В общем, мой совет - следовать любому установленному стандарту кодирования, если он есть: для WordPress это означает использование условий Yoda.

Когда нет, и невозможно установить его путем консенсуса с вашими коллегами, это выбор дилера.

Attila
источник
2
Я помню, когда разрабатывал язык (давным-давно), который мы специально сделали :=оператором присваивания (с помощью ==теста на равенство), чтобы избежать такого рода проблем.
Donal Fellows
7
Я написал много, много строк кода, и я никогда не вводил случайно =вместо ==. Разница настолько подчеркнута везде, что я просто никогда не путаю их. С другой стороны, я прочитал много частей кода, которые сбивают с толку или иным образом трудно понять. Поэтому я бы поставил приоритеты на удобочитаемость :). В любом случае, хороший ответ.
crazy2be
5
Еще одна веская причина для использования -Wall -Werrorили эквивалент вашего компилятора / интерпретатора. Есть очень немного ситуаций, когда назначение внутри условия является правильным, не говоря уже о том, что оно более читабельно. Многие языки этого даже не позволяют.
Карл Билефельдт
7
Pedantic: В то время как имеет if($foo = 1)значение trueв некоторых языках, в PHP это имеет значение 1 вместо; if($foo = 20)оценивает до 20; if($foo = 0)оценивается в 0, что в отличие от других является ложным. Это может добавить еще один слой сложности к ошибке.
Чарльз
2
На самом деле, стандарты кодирования WordPress действительно требуют условных кодов
Том Огер,
13

Это защитный механизм кодирования, предназначенный для предотвращения случайного использования оператора присваивания.

Рассмотрим неправильное использование / ошибку оператора присваивания вместо оператора равенства

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

Приведенное выше условие всегда будет возвращать true, но, вероятно, это не то, что имел в виду оригинальный программист. Считайте, что в этом месте это

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); может дать вам предупреждение, что заявление никогда не выполняется; оператор if ((false)); не дает этого предупреждения.

gnasher729
источник
Мне это очень нравится! Я избегаю следующих, совершенно законных идиом в PHP, потому что я всегда получаю предупреждения в своей IDE:if ($array = getSomething()){ // ..so something with $array }
Том Аугер