Лучший способ отформатировать оператор if с несколькими условиями

Если вы хотите, чтобы какой-то код выполнялся на основе двух или более условий, как лучше всего отформатировать этот оператор if?

первый пример: -

if (ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Второй пример: -

if (ConditionOne)
{
   if (ConditionTwo )
   {
     if (ConditionThree)
     {
       Code to execute
     }
   }
}

что легче всего понять и прочитать, имея в виду, что каждое условие может быть длинным именем функции или чем-то еще.

Жалко, что никто на этой странице не упоминает подстроку «быстро» или «производительность». Это то, что я пришел сюда, чтобы узнать.

Dreamspace President 19.05.2019 13:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
90
1
358 603
10

Ответы 10

Первый вариант проще, потому что, если вы читаете его слева направо, вы получите: «Если что-то И что-то другое И что-то еще ТО», это простое для понимания предложение. Второй пример гласит: «Если что-то ТО, если что-то еще ТО, если что-то еще ТО», что неуклюже.

Кроме того, подумайте, хотите ли вы использовать несколько операторов OR в своем предложении - как бы вы это сделали во втором стиле?

Другие ответы объясняют, почему обычно лучше всего первый вариант. Но если у вас несколько условий, подумайте о создании отдельной функции (или свойства), выполняющей проверку условий в варианте 1. Это значительно упрощает чтение кода, по крайней мере, когда вы используете правильные имена методов.

if (MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Если условия зависят только от переменных локальной области видимости, вы можете сделать новую функцию статической и передать все, что вам нужно. Если есть микс, передайте местный материал.

Я обнаружил, что это наиболее эффективный и простой способ добавить условия позже.

pbojinov 25.11.2011 13:23

+1 сначала я приподнял бровь но это действительно лучший ответ имхо. наличие этого логического isOkToDoWhatever в качестве свойства имеет большой смысл.

grinch 08.11.2012 05:30

Но это просто перемещает то же сложное условие в другое место, где он также должен быть читабельным, так что мы вернулись к исходной точке с этим. Дело не только в удобочитаемости ifstatement, но и в удобочитаемости условий.

Robert Koritnik 17.05.2016 11:15

@RobertKoritnik Я понимаю, о чем вы говорите, но не думаю, что мы вернулись к исходной точке, потому что мы снизили сложность, которую читатель должен учитывать за один раз. Она может посмотреть на условия, ИЛИ она может посмотреть на код, используя условия, в которых условия имеют (надеюсь) красивое имя. По крайней мере, мне часто легче это понять, но, опять же, иногда приятно собрать все детали в одном месте. Как всегда, зависит от обстоятельств.

Torbjørn 27.05.2016 02:03

Отличный смысл использовать хорошие имена методов и рефакторинг логики.

JB Lovell 27.01.2017 05:52

Я предпочитаю вариант А

bool a, b, c;

if ( a && b && c )
{
   //This is neat & readable
}

Если у вас есть особенно длинные переменные / условия метода, вы можете просто разорвать их на строку

if ( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Если они еще более сложные, я бы подумал о том, чтобы делать методы условия отдельно, вне оператора if.

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if ( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO Единственная причина для варианта «B» - это если у вас есть отдельные функции else, которые нужно запускать для каждого условия.

например

if ( a )
{
    if ( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

Мне это нравится. Хотя я не большой поклонник идеи метода, если только методы уже не существуют и не возвращают логическое значение.

Thomas Owens 03.11.2008 20:26

Разве во втором примере вы не оцениваете все без причины?

Odys 24.12.2016 19:19

Я бы использовал "&&" перед условием. Трудно иметь условия с такой же длиной символа, как в примере.

Darkov 04.08.2020 14:03

Первый пример более «читается».

На самом деле, на мой взгляд, вы должны использовать только второй вариант, когда вам нужно добавить некоторую «логику else», но для простого Conditional используйте первый вариант. Если вас беспокоит длина условия, вы всегда можете использовать следующий синтаксис:

if (ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

Удачи!

Второй - классический пример Стрелка Анти-узор, поэтому я бы его избегал ...

Если ваши условия слишком длинные, извлеките их в методы / свойства.

Вопрос был задан и до сих пор получен ответ, как будто решение должно приниматься исключительно на «синтаксических» основаниях.

Я бы сказал, что правильный ответ о том, как вы выкладываете ряд условий в if, должен тоже зависит от «семантики». Таким образом, условия должны быть разбиты и сгруппированы в соответствии с тем, что «концептуально» сочетается.

Если два теста действительно являются двумя сторонами одной медали, например. если (x> 0) && (x <= 100), то поместите их в одну строку. Если другое условие концептуально гораздо более отдаленное, например. user.hasPermission (Admin ()), затем поместите его в отдельную строку

Например.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}

В Perl вы могли сделать это:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Если какое-либо из условий не выполняется, он просто продолжится после блока. Если вы определяете какие-либо переменные, которые хотите сохранить после блока, вам нужно будет определить их до блока.

Вот и смотрит Перлиш - в графе "ЧТО делает?" смысл;) Но на самом деле он читается, как только вы к нему привыкнете.

Piskvor left the building 20.08.2010 17:35

Когда условие действительно сложное, я использую следующий стиль (пример из реальной жизни PHP):

if ( $format_bool &&
    (
        ( isset( $column_info['native_type'] )
            && stripos( $column_info['native_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['driver:decl_type'] )
            && stripos( $column_info['driver:decl_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['pdo_type'] )
            && $column_info['pdo_type'] == PDO::PARAM_BOOL
        )
    )
)

Я считаю, что это более удобно и читабельно, чем вложение нескольких уровней if (). И в некоторых случаях, подобных этому, вы просто не можете разбить сложное условие на части, потому что в противном случае вам пришлось бы повторять одни и те же операторы в блоке if () {...} много раз.

Я также считаю, что добавление «воздуха» в код - всегда хорошая идея. Это значительно улучшает читаемость.

if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

Форматирование нескольких условных выражений в операторе if-else следующим образом:

  1. обеспечивает улучшенную читаемость:
    а. все двоичные логические операции {&&, ||} в выражении, показанном первым
    б. оба условных операнда каждой бинарной операции очевидны, потому что они выровнены по вертикали c. Операции вложенных логических выражений становятся очевидными с помощью отступов, как и вложения операторов внутри предложения
  2. требует явных скобок (не полагаться на правила приоритета операторов)
    а. это позволяет избежать распространенных ошибок статического анализа
  3. позволяет упростить отладку а. отключить отдельные одиночные условные тесты с помощью //
    б. установить точку останова непосредственно перед или после любого отдельного теста c. например ...
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if (   1
    && ( single conditional expression A )
    && ( single conditional expression B )
    && (   0
        || ( single conditional expression C )
        || ( single conditional expression D )
       )
   )
{
   ... ;
}

else
{
   ... ;
}

Это мой метод. Единственная проблема, с которой я столкнулся, - мне еще предстоит найти средство для украшения кода, которое предлагает это в качестве опции.

Speed8ump 25.07.2019 18:04

Я столкнулся с этой дилеммой долгое время и до сих пор не могу найти правильного решения. На мой взгляд, единственный хороший способ - это сначала попытаться избавиться от состояний раньше, чтобы вы не сравнивали сразу 5 из них.

Если альтернативы нет, то, как предлагали другие, - разбейте ее на отдельные и сократите имена или сгруппируйте их и, например, если все должно быть истинным, используйте что-то вроде «если в массиве x нет false, то запустить».

Если ничего не получится, @Eoin Campbell высказал неплохие идеи.

Это не добавляет ничего нового к уже существующим ответам.

jerney 17.08.2018 19:44

Другие вопросы по теме