Лучший способ отформатировать оператор if с несколькими условиями - PullRequest
79 голосов
/ 31 октября 2008

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

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

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

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

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

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

Ответы [ 11 ]

121 голосов
/ 31 октября 2008

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

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 ;)
}

ИМХО Единственная причина для опции 'B' заключается в том, что у вас есть отдельные else функции для запуска для каждого условия.

, например

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}
28 голосов
/ 31 октября 2008

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

if(MyChecksAreOk()) { Code to execute }

...

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

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

9 голосов
/ 31 октября 2008

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

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

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

Например.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}
9 голосов
/ 31 октября 2008

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

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

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

Удачи!

5 голосов
/ 20 апреля 2017
    if (   ( single conditional expression A )
        && ( single conditional expression B )
        && ( single conditional expression C )
       )
    {
       opAllABC();
    }
    else
    {
       opNoneABC();
    }

Formatting a multiple conditional expressions in an if-else statement this way:
1) allows for enhanced readability:
    a) all binary logical operations {&&, ||} in the expression shown
       first
    b) both conditional operands of each binary operation are obvious
       because they align vertically
    c) nested logical expressions operations are made obvious using
       indentation, just like nesting statements inside clause
2) requires explicit parenthesis (not rely on operator precedence rules)
    a) this avoids a common static analysis errors
3) allows for easier debugging
    a) disable individual single conditional tests with just a //
    b) set a break point just before or after any individual test
    c) e.g. ...

    // 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
    {
       ... ;
    }
4 голосов
/ 31 октября 2008

Второй является классическим примером Arrow Anti-pattern Так что я бы его избежал ...

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

3 голосов
/ 31 октября 2008

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

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

2 голосов
/ 03 декабря 2014

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

switch (//variable or Boolean) {
  case //Condition A:
  case //Condition B:
  case //Condition C:
    //Code to execute;
}
0 голосов
/ 17 августа 2018

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

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

Если не получится, @Eoin Campbell дал довольно хорошие идеи.

0 голосов
/ 21 февраля 2015

Когда условие действительно сложное, я использую следующий стиль (пример реальной жизни 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() {...} много раз.

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

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