Комментарии 33
В моей практике сложное условие часто разбивается на несколько простых, под результат которых выделяются переменные, и в if идут только эти переменные. Например (код искусственный):
Не знаю, согласуется ли такой подход с тем что советуют профессионалы, но субъективно — так легче читаются на лету составные части условия.
bool mustRdraw = (frame.isChanged() || target.isChanged()) || experiment.isRunning();
bool isFullScreen = frame.getSize().equal(screen.getSize());
if (isFullScreen && mustRedraw) {
// redraw
}
Не знаю, согласуется ли такой подход с тем что советуют профессионалы, но субъективно — так легче читаются на лету составные части условия.
+23
Иногда проверки должны идти в строго заданном порядке и если одна будет ложной, то следующие проверять нельзя. Тогда подход с переменными становится бесполезным и приходится городить либо вложенные условия, либо сложные, а так – полезная практика.
+1
В C# я часто для этого использовал функции
Func<bool> mustDraw = () => (frame.isChanged() || target.isChanged()) || experiment.isRunning();
Func<bool> isFullScreen = () => frame.getSize().equal(screen.getSize());
if (isFullScreen() && mustRedraw()) {
// redraw
}
0
мне тоже нравится такой подход, отчасти тем, что значения переменных легко посмотреть в дебаггере
+1
bool mustRdraw = (frame.isChanged() || target.isChanged()) || experiment.isRunning(); bool isFullScreen = frame.getSize().equal(screen.getSize()); if (isFullScreen && mustRedraw) { // redraw }
Допустим, что где-то вверху объявлена bool mustRedraw…
И… Бум!!!
+1
Для себя выработал правило Yoda conditions + автоматическое форматирование + выделение сложных условий в функции или переменные. Потому что, честно говоря, эти отступы и рюшки хороши пока у кода один хозяин — да и то не долго. Каждое изменение такого условия порождает переформатирование, что бы красиво было… Это уже ASCII Art, получается, а не программирование.
+2
Я использую для таких условий нечто вроде:
if ( true
&& condition1
&& ( false
|| condition_2_1
|| condition_2_2
)
) {
// do something
}
+1
Поступаю аналогично. Очень удобно построчно переносить код а также использовать условную компиляцию. Особенно такие конструкции разрастаются в sql (при этом true заменяется на 1=1). А для сложных случаев в комментариях описывается сначала таблица истинности, по которой, собственно, и составляется условие.
+4
Спасибо. Красиво, и почти соответствует последнему примеру.
Но, наверно, лучше, если по команде редактор покажет код условия в виде дерева, да еще и посоветует минимальную группировку выражения
Но, наверно, лучше, если по команде редактор покажет код условия в виде дерева, да еще и посоветует минимальную группировку выражения
-1
А true и false просто для того, чтобы не оставлять пустые открывающие скобки? Получается же и избыточность, и увеличение сложности. Стоит ли оно того?
0
Не совсем удобно. Любой мысль в коде должна быть или завершенной полностью, к примеру вызов метода с его аргументами на одной строке, либо явно намекать на то что «to be continue», т.е. ищи продолжение. Когда вы пишите && связывая под-условия, лучше всего это делать на одной строке, а продолжение мысли, т.е. написание след. под-условия на второй. Потому что когда Вы смотрите:
if ( file.Exists() &&
то Вы сразу понимаете, что мысль не завершена! Следовательно надо читать мысль(условие) далее!
И того Ваш кусок кода, при использовании моего предложения будет выглядеть так:
if ( true &&
condition1 &&
( false ||
condition_2_1 || condition_2_2 )
) {
// do something
}
Но я бы сделал так:
bool subCondition1 = true && condition1;
bool subCondition2 = false || (condition_2_1 || condition_2_2);
if (subCondition1 && subCondition2 ) {
// more code
}
P.S.: Сорри за то что не применяю тег код, он недоступен на хабре тем у кого карма ниже нуля.
if ( file.Exists() &&
то Вы сразу понимаете, что мысль не завершена! Следовательно надо читать мысль(условие) далее!
И того Ваш кусок кода, при использовании моего предложения будет выглядеть так:
if ( true &&
condition1 &&
( false ||
condition_2_1 || condition_2_2 )
) {
// do something
}
Но я бы сделал так:
bool subCondition1 = true && condition1;
bool subCondition2 = false || (condition_2_1 || condition_2_2);
if (subCondition1 && subCondition2 ) {
// more code
}
P.S.: Сорри за то что не применяю тег код, он недоступен на хабре тем у кого карма ниже нуля.
+2
C предварительным вычислением условий есть небольшая засада.
Иногда вычисление какого-то условия является «тяжелой» операцией и часто не требуется.
Если мы расписываем условия в одном if, без предвычислений, то за счет lazy ops такие вычисления можно пропустить, что не всегда возможно при предвычислениях.
Иногда вычисление какого-то условия является «тяжелой» операцией и часто не требуется.
Если мы расписываем условия в одном if, без предвычислений, то за счет lazy ops такие вычисления можно пропустить, что не всегда возможно при предвычислениях.
0
1) Преждевременная оптимизация, что?
2) Никто не отменял составлять под-условия по их наиболее вероятному состоянию.
2) Никто не отменял составлять под-условия по их наиболее вероятному состоянию.
0
НЛО прилетело и опубликовало эту надпись здесь
И в вашем стиле ставить true или false перед остальными условиями бессмысленно. Вам подошла запись вида
Но в таком виде ни у кого не видел :)
if (
condition1 &&
(
condition2_1 ||
condition2_2 ||
false
) &&
true
) {
// do something
}
Но в таком виде ни у кого не видел :)
+1
Возможно, глупый вопрос, но зачем в таком варианте вообще true и false?
+3
Для единообразной записи условий, например. В таком виде условия можно копировать, перемещать, добавлять и удалять всегда в одной и той же манере, вне зависимости от их расположения.
+1
Не аргумент! Т.к. вызывает вопросы, товарищь gwer совсем не глупый вопрос задал!
-2
Некоторые явления кажутся нам очевидными лишь из-за того, что они повсеместно используются.
Я задал вопрос потому, что встретил сие впервые (осмысленно). Но это действительно плюс для форматированных условий.
С другой стороны, так ли часто это дает какой-либо достаточно весомый выигрыш для того, чтобы ради этого и без того сложное условие загромождать новыми элементами?
Я задал вопрос потому, что встретил сие впервые (осмысленно). Но это действительно плюс для форматированных условий.
С другой стороны, так ли часто это дает какой-либо достаточно весомый выигрыш для того, чтобы ради этого и без того сложное условие загромождать новыми элементами?
0
Поверьте — условия, записанные таким образом, читаются легче. Ведь вся разница только в наличии true/false при открывающей скобке, — а в остальном все очень даже мимими.
Просто попробуйте в своем коде так переформатировать пару if.
Просто попробуйте в своем коде так переформатировать пару if.
0
Смотрится убого! Полезность нулевая. Посмотрел в коде Linux и FreeBSD нигде подобной записи условий не увидел. Видимо для прикладников это имеет значение, а вот что-то системщики что-то не жалуют или я плохо искал пример, тогда прошу дать ссылку на сорец из реальных боевых программ прошедших испытание временем
0
На мой взгляд, если изменить style guide и вместо записи
записть
то визуально это будет выглядет как две лексемы, а не четыре, и читать будет легче.
isnan (src) || isinf (src))
записть
isnan(src) || isinf(src))
,то визуально это будет выглядет как две лексемы, а не четыре, и читать будет легче.
+2
Согласен, пробелы очень сильно влияют на читаемость. Аналогичная ситуация, например, с приведением типов и с отрицаниями. Приведение в примерах есть, а вот отрицание в выборку интересных условий попало, но до статьи не дошло.
libgcc/libgcc2.c — 1611:
Пробелы эти, на мой взгляд, ни к чему. Кстати, это еще один вариант совокупности описанных решений. Многострочное условие вкупе с вложенным условным оператором.
libgcc/libgcc2.c — 1611:
if (! (- ((DWtype) 1 << FSIZE) < u
&& u < ((DWtype) 1 << FSIZE)))
{
if ((UDWtype) u & (REP_BIT - 1))
{
u &= ~ (REP_BIT - 1);
u |= REP_BIT;
}
}
Пробелы эти, на мой взгляд, ни к чему. Кстати, это еще один вариант совокупности описанных решений. Многострочное условие вкупе с вложенным условным оператором.
0
>>Возможно, я не там искал, но ни разу в стандартах оформления кода не встречал упоминаний о том, как быть со сложными условиями.
Да, не там! Стив Макконнелл «Совершенный код». Также есть книга «Чистый код» от Мартина и там тоже это все описывается! Эти книги «must read», если Вы еще не читали, то настоятельно рекомендую, хоть 1% полезности из них но возьмете!
Да, не там! Стив Макконнелл «Совершенный код». Также есть книга «Чистый код» от Мартина и там тоже это все описывается! Эти книги «must read», если Вы еще не читали, то настоятельно рекомендую, хоть 1% полезности из них но возьмете!
+1
Макконнелл предлагал разбивать условие на переменные или функции. Это хороший подход. Но группируемые подусловия должны быть логично связаны, то есть вводимая функция/переменная является эдаким слоем абстракции. Но вдруг условие требуется очень сложное, и получилось что-то из следующего списка:
Или еще какая-то ситуация, когда нужно написать сложное условие. Как поступим?
К слову, в примере Макконнелла на эту тему сложное условие, разбитое на три строки, которое он называет ужасным, на мой взгляд, выглядит лучше и понятнее, нежели то, что он нагородил с функцией и переменными.
А вот у Мартина не помню упоминаний этой темы. Процитируете?
- Условие состоит из большого числа слабо связанных подусловий, которые затруднительно логично и красиво разбить.
- Мы выделили функции/переменные, но их много, и даже с ними условие воспринимается не очень хорошо.
- Мы выделили функции/переменные, конечное условие красивое и наглядное, но в функциях/переменных теперь сложные условия.
Или еще какая-то ситуация, когда нужно написать сложное условие. Как поступим?
К слову, в примере Макконнелла на эту тему сложное условие, разбитое на три строки, которое он называет ужасным, на мой взгляд, выглядит лучше и понятнее, нежели то, что он нагородил с функцией и переменными.
А вот у Мартина не помню упоминаний этой темы. Процитируете?
0
В разделе «Функции» Мартин просто в своём примере заменяет условие на функцию, никак на этом особо не заостряя внимание.
А вот Мартин Фаулер в «Рефакторинге» как раз вводит понятия «Декомпозиция условного оператора» и «Консолидация условного оператора», которые связаны с выделением условий в функции. В книге это всё описано в целом разделе «Упрощение условных выражений», в общем, есть что почитать в рамках данного вопроса
А вот Мартин Фаулер в «Рефакторинге» как раз вводит понятия «Декомпозиция условного оператора» и «Консолидация условного оператора», которые связаны с выделением условий в функции. В книге это всё описано в целом разделе «Упрощение условных выражений», в общем, есть что почитать в рамках данного вопроса
+2
Да, вы правы, он приводил пример! Я же программист, когда читаю техническую книгу то отлично понимаю что мне надо не только представлять что происходит, но и почему! Т.е. «видеть код»!!! Поэтому для меня любой пример, почти что «абзац написанный словами». Бывают хорошие «абзацы», а бывают такие что следует взять на заметку! Да и люблю читать чужие исходные код, в конечном итоге многому учишься сам того не осознавая )
0
В продолжение темы — еще есть проблема вложенных многоуровневых условий.
С этим метод борьбы простой. Надо вместо
писать
Не помню точно первоисточника, но вроде бы это было еще у Дейкстры.
С этим метод борьбы простой. Надо вместо
if(a) {
if(b) {
op1;
if(c) op2;
op3;
}
} else {
if(!c) {
op4;
}
}
писать
if(a && b) op1;
if(a && b && c) op2;
if(a && b) op3;
if(!a && !c) op4;
Не помню точно первоисточника, но вроде бы это было еще у Дейкстры.
+2
Сам я тоже пришел к стилю как в примере выше в «libgcc/libgcov-driver.c — 688:», кажется самым наглядным из всех.
0
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Оформление сложных условий