Что положить в блок IF и что положить в блок ELSE? - PullRequest
12 голосов
/ 03 октября 2008

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

Итак, если у вас есть:

if (condition) then
{
   // do stuff
}
else
{
   // do other stuff
}

Как вы решаете, лучше это или так:

   if (!condition) then
   {
     // do other stuff
   {
   else
   {
     // do stuff
   }

Мои эвристики:

  1. Сохранять состояние положительным (меньше умственный расчет при чтении)
  2. Поместите самый распространенный путь в первый блок

Ответы [ 23 ]

18 голосов
/ 03 октября 2008

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

if (condition)
    return;

DoSomething();

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

4 голосов
/ 03 октября 2008

Две (противоречивые) цитаты из учебника:

Поместите кратчайшее предложение из if / else сверху

- Аллен Голуб, «Хватит веревки, чтобы выстрелить себе в ногу», с.

Поставьте нормальный регистр после if, а не после else

- Стив Макконнелл, «Код завершен, 2-е изд.», С.

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

Если код предназначен для проверки состояния ошибки, я предпочитаю ставить этот код первым, а «успешный» код - вторым; концептуально это сохраняет вызов функции и код проверки ошибок вместе, что имеет смысл для меня, потому что они связаны между собой. Например:

  if (!some_function_that_could_fail())
  {
     // Error handling code
  }
  else
  {
     // Success code
  }
3 голосов
/ 03 октября 2008

Это зависит от вашего потока. Для многих функций я буду использовать предварительные условия:

bool MyFunc(variable) {
    if (variable != something_i_want)
        return false;

    // a large block of code
    // ...
    return true;
}

Если мне нужно делать что-то в каждом случае, я буду использовать формат if (positive_clause) {} else {}.

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

Я согласен с Оли при использовании положительного предложения if, когда это возможно.

Просто, пожалуйста, никогда не делай этого:

if (somePositiveCondition)
else {
    //stuff
}

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

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

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

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

Когда я смотрю на проверку данных, я пытаюсь сделать мои условия "белым списком" - то есть я проверяю, что я приму:

if DataIsGood() then
   DoMyNormalStuff
else
   TakeEvasiveAction

Вместо наоборот, который имеет тенденцию вырождаться в:

if SomeErrorTest then
  TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
  CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
  DoMoreErrorHandling
else
  DoMyNormalStuff
2 голосов
/ 03 октября 2008

Если один из двух путей очень короткий (от 1 до 10 строк или около того), а другой намного длиннее, я следую упомянутому здесь правилу Holub и помещаю более короткий фрагмент кода в if , Это облегчает просмотр потока if / else на одном экране при просмотре кода.

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

2 голосов
/ 03 октября 2008

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

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

А как насчет ситуации, когда «обычный» случай ничего не делает? Что тогда

if( common ) {
    // pass
}
else {
    // great big block of exception-handling folderol
}

Или ты это делаешь?

if( ! common ) {
    // great big block of except-handling folderol
}

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

  1. Всегда естественный - он должен читаться как английский (или любой другой язык в вашей организации).
  2. Там, где это возможно, сначала распространены общие случаи, поэтому они кажутся общими.
  3. Где возможно, используйте позитивную логику; Негативную логику можно использовать там, где так обычно говорят, или в том случае, когда обычным делом является бездействие.
2 голосов
/ 03 октября 2008

Я думаю, что для одной переменной оператор not достаточно прост, и вопросы именования становятся более актуальными.

Никогда не называйте переменную not_X, если нужно, используйте тезаурус и найдите противоположность. Я видел много ужасного кода вроде

if (not_dead) {
} else {
}

вместо очевидного

if (alive) {
} else {
}

Тогда вы можете разумно использовать (очень читабельно, нет необходимости инвертировать блоки кода)

if (!alive) {
} else {
}

Если мы говорим о большем количестве переменных, я думаю, что лучшим правилом является упрощение условия. Через некоторое время проекты, как правило, получают условия, такие как:

if (dead || (!dead && sleeping)) {
} else {
}

Что переводится как

if (dead || sleeping) {
} else {
}

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

...