Условия в петлях, лучшие практики? - PullRequest
9 голосов
/ 17 января 2012

Скажем, у меня есть такой цикл:

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
        continue;
    }
    doSomeOtherStuff();
}

По сравнению с ...

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
    }
    else
    {
        doSomeOtherStuff();
    }
}

Есть ли причина использовать один цикл над другим?Или это просто личные предпочтения?
Основной язык, о котором я спрашиваю, - это Java, но, полагаю, это относится и к большинству других.

Ответы [ 8 ]

16 голосов
/ 17 января 2012

Технически, нет, но я считаю, что второй вариант красивее для этого конкретного случая.

7 голосов
/ 17 января 2012

Я предпочитаю вторую конструкцию ...

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
        //lets say lot of code
        //..
        //...
        //...
        //...
        continue;
    }
    else
    {
        doSomeOtherStuff();
    }
}

Допустим, у вас было много кода до continue.Это сразу видно, просто взглянув на

   else
    {
        doSomeOtherStuff();
    }

, если он не выполнен безоговорочно .

5 голосов
/ 17 января 2012

Для меня это зависит от того, какова разница между относительными размерами ветвей then и else: если один значительно больше другого, а меньший представляет логически исключительную ситуацию, я ставлю более короткуюв then и добавьте continue;когда они примерно равны, как по размеру, так и по логическому потоку, я сохраняю их в своих then и else ветвях.

for (String tok : tokens) {
    if (isKeyword(tok)) {
         output.write(tok);
         continue;
    }
    // Do some massive processing of non-keyword tokens here
    // This block goes on...
    // and on...
    // and on... You get the idea
}

против

for (String op : operators) {
    if (isAdditive(op)) {
        // Do something for additive ops
    } else {
        // Do something for non-additive ops
    }
}
2 голосов
/ 17 января 2012

Как все говорили, рекомендуется вторая форма. Многие стандарты кодирования рекомендуют избегать операторов «continue» и «break», поскольку это усложняет ваш код.

Просто чтобы дать вам ссылку:

JSF ++ (Правило 190) и Мисра С (Правило 57) говорят:

Оператор continue не должен использоваться.

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

Мисре платят, но JSF ++ можно скачать бесплатно здесь:

http://www.jsf.mil/downloads/documents/JSF_AV_C++_Coding_Standards_Rev_C.doc

Это для C ++, но многие правила могут быть применены к другим языкам. Это стоит чтения!

2 голосов
/ 17 января 2012

Я бы определенно предпочел второй синтаксис.

Старайтесь по возможности избегать операторов продолжения.Это усложняет путь к коду и затрудняет отладку

1 голос
/ 17 января 2012

В этом конкретном случае я согласен со всеми остальными, что второе предпочтительнее.Но бывают случаи, когда я бы пошел первым.Если бы DoSomething() был на самом деле всего лишь одним этим вызовом, а i == someCondition - это крайний случай, а doSomeOtherStuff() были бы на самом деле 20 строками кода, а не только этим одним вызовом, то я бы предпочел использовать continue.В этом сценарии я читал его как «во-первых, давайте быстро позаботимся об этом одном крайнем случае. Хорошо, теперь давайте сделаем реальные вещи».

Конечно, можно аргументировать if-elseперефразируя мою интерпретацию следующим образом: «если мы находимся в крайнем случае, сделайте это, иначе сделайте реальные вещи».Но это означает, что все эти 20 строк теперь на одну вложенность глубже, и для меня более читабельно сначала позаботиться о крайних случаях, а затем сосредоточиться на общем пути.

0 голосов
/ 17 января 2012

Я думаю, это зависит больше от того, что вы делаете.

Это простой пример, но, как правило, если есть условие, которое я «извлекаю» из другой логики цикла, я вытащу его как можно быстрее с продолжением, а не добавлю к сложности будущего операторы if (ваш первый пример IF, это условие, которое можно извлечь, упрощая будущую логику) Например:

for ( int i = 0 ; i < n ; i++ )
{
    if( obj[i] != null && obj[i].instanceOf("A")) {
        doSomething();
    } else if(obj[i] != null && obj[i].instanceOf("B"){
        doSomethingElse();
    }
}

СЕЙЧАС ясно, что извлечение первого условия в

if(obj[i] == null) {
    continue;
}

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

Кроме того (это полностью сторонний подход, а не часть ответа вообще!), Я бы сказал, что если вы когда-нибудь увидите «действительно» сбалансированное состояние, вы можете серьезно подумать над дизайном ОО. Если doSomething и someOtherCondition были одинаковыми, они, вероятно, должны быть различными реализациями метода, определенного в базовом классе или интерфейсе, что приводит к следующему коду:

for ( int i = 0 ; i < n ; i++ )
{
    obj[i].doSomething();
}
0 голосов
/ 17 января 2012

Я на самом деле полагаю, что есть веская причина предпочесть первое вместо второго, , хотя в большинстве случаев второе определенно более читабельно .

Скажем, например, у вас естьмного, и я имею в виду множество условий в вашем цикле, где наличие множества if операторов фактически влияет на читабельность посредством отступа:

for ( int i = 0 ; i < n ; i++ )
{
   if ( obj[i] )
   {
      doSomething();
      if ( someOtherCondition() 
      {
           //...........
                                                  if ( /* some levels down */ )
                                                  {

                                                  }
           //.....
      }  
   }
}

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

Так что вы можете рефакторинг и сделать его намного более читабельным с помощью:

for ( int i = 0 ; i < n ; i++ )
{
   if ( !obj[i] )
   {
       continue;
   }
   doSomething();
   if ( !someOtherCondition() 
   {
       continue;
   }
   //...........  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...