If (x!= y) vs if (x == y)
Я запустил плагин PMD в Eclipse против моего кода, и я получаю предупреждение с высоким приоритетом для кода, аналогичного показанному ниже:
if(singleRequest !=null){
// do my work
}else{
// do my other work
}
PMD говорит `Avoid if (x != y) ..; else ..
;
И описание ошибки выглядит следующим образом:
In an "if" expression with an "else" clause, avoid negation in
the test. For example, rephrase:
if (x != y) diff(); else same();
as:
if (x == y) same(); else diff();
Most "if (x != y)" cases without an "else" are often return
но я все еще не могу понять влияние моего кода. Если бы кто-нибудь мог привести меня к примеру, я был бы признателен.
Ответы
Ответ 1
Ряд правил PMD - это скорее мнения стиля, чем предупреждения о правильности. Если вы не согласны с этим правилом или правило не соответствует вашим стандартам кодирования проекта, вы можете рассмотреть подавление предупреждений или даже настройка PMD для обеспечения соблюдения только тех правил, которые вам нравятся
Ответ 2
PMD - это инструмент. PMD работает на основе эвристики. Кто-то решил эту эвристику; что отрицательные условные выражения с инструкциями else не являются "хорошим стилем".
Однако в этом случае, как я уже говорил в своих комментариях, опубликованный код - это как I. (В частности, с x != null
, но не исключительно для этой конструкции.)
Это потому, что я не смотрю на условное (за исключением того, что его можно упростить, например, удаление двойных негативов, как показано Джим Кином), но я смотрю на логику ветвей или "поток".
То есть, я положил первую положительную ветвь. В этом случае я утверждаю, что
if (x != null) {
doValid // positive branch
} else {
doFallback
}
семантически эквивалентно
if (isValid(x)) { // it looks like a "positive conditional" now
doValid // still positive branch
} else {
doFallback
}
и, таким образом, является положительной ветвью.
Конечно, не во всех ситуациях есть такой "ясный" положительный поток, и некоторые выражения могут быть выражены намного проще отрицательным образом. В этих случаях я буду "инвертировать" ветки - подобно тому, что предлагает PMD - обычно с комментарием, указывающим действие в верхней части блока, если положительная ветвь/поток была отменена.
Другим фактором, который может повлиять на выбранный условный выбор, является "немедленная область действия", например:
if (x == null) {
// return, break, or
throw new Exception("oops!");
} else {
// But in this case, the else is silly
// and should be removed for clarity (IMOHO) which,
// if done, avoids the PMD warning entirely
}
Вот как I последовательно (несколько отдельных исключений) записывает мой код: if (x != null) { .. }
. Используйте доступные инструменты; и заставить их работать на вас. См. Ответ Стивена о том, как PMD можно настроить на более подходящий "вкус" здесь.
Ответ 3
Это проблема читаемости. Рассмотрим
if ( x != y )
{
}
else // "if x doesn't not equal y"
{
}
против.
if ( x == y )
{
}
else // "if x doesn't equal y"
{
}
Последний пример более точно идентифицируется. Имейте в виду, я не вижу ничего плохого в использовании негативов... это может сделать намного больше смысла, подумайте
if ( x != null )...
Ответ 4
Единственная причина, по которой я избегу использовать отрицательный случай, - это привести к двойным негативам, что может сбить с толку.
например.
if (!checkbox.disabled) {
// checkbox is enabled
}
else {
// checkbox is disabled
}
Ответ 5
Кто читает ваш код? Вы делаете. Компилятор делает. Или, может быть, помощник лектора. Сотрудник, который не может различать == и! =? Надеюсь, что нет.
Я могу только думать, что негативы плохи в сложных выражениях. (Контекст: по крайней мере для меня. Я знаю, что я расстроен в отладке в голове while(!expr && !expr2 || expr3) { }
)
ch=getch(); if (ch!='a')
- это шаблон, который легко распространяется на
if (ch!='a' || ch!='b')
, которая всегда истинна, при этом звучание семантически корректно.
С точки зрения производительности лучше всего отсортировать вероятности.
if (more_probable) {
....
unconditional_jump_to_end_of_block;
} else {
...
}
Этот выбор должен привести к повышению производительности, поскольку в более вероятной ветке нет штрафа за неправильное предсказание.
if (p && p->next)
, оцененный с точки зрения производительности, дает плохие результаты.
Ответ 6
Вам нужно избегать "не равных" в условии if. Это связано с тем, что, когда кто-то еще смотрит на ваш код, существует реальная возможность, что человек может игнорировать!= И может ошибиться в логике вашей программы.
В вашем случае вам может потребоваться обмен логикой if с логикой else и изменением!= to ==
Ответ 7
Это балансирующий случай чтения кода и организации кода. Предупреждение в основном предполагает, что это путано для людей, читающих код, для перемещения отрицания отрицательного.
Мое личное эмпирическое правило заключается в том, что вы ожидаете быть "нормальным" случаем - это то, что вы должны проверить в if. Рассмотрим:
if (x != y) {
// do work here...
} else {
throw new IllegalArgumentException();
}
В этой ситуации я бы сказал, что важная работа выполняется в случае x != y
, так что вы должны проверить. Это связано с тем, что мне нравится организовывать код, чтобы на первом месте была важная работа, а затем выполнялась обработка исключительных случаев.
Ответ 8
Это потому, что "хороший стиль" говорит, что если возможные тесты должны быть "положительными", значит:
if (singleRequest == null){
// do my other work
} else {
// do my work
}
Легче читать, потому что тест "положительный" (т.е. "равно" не "не равно" ), и в конечном итоге улучшенная читаемость приводит к меньшим ошибкам.
Edited
Это особенно относится к тесту, например:
if (!str.equals("foo")) {
вы можете легко пропустить !
спереди, но если вы сделаете тест положительным, он будет намного чище.
Единственный раз, когда у вас должен быть отрицательный тест, нет блока else
- тогда отрицательный тест неизбежен, если у вас нет пустого блока true
, который сам по себе считается проблемой стиля.
Ответ 9
На самом деле не ответ, но вы можете свести к минимуму общую сложность и улучшить читаемость, вернувшись или не получив раннее, а затем продолжая без отступов:
if (something == null) {
throw new IllegalArgumentException("something must not be null");
}
// continue here