Что положить в блок 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 ]

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

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

Пример:

if (blah == false)
{
    return; // perhaps with a message
}

// do rest of code here...

Есть несколько хардкорных парней c / c ++ / Assembly, которые скажут вам, что вы уничтожаете свой процессор !!! (во многих случаях процессоры предпочитают выражение «истина» и пытаются «предварительно выбрать» следующее, что нужно сделать ... поэтому теоретически любое «ложное» условие очистит канал и замедлит микросекунды).

По моему мнению, мы находимся в точке, где «лучший» (более понятный) код выигрывает за микросекунды процессорного времени.

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

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

С другой стороны, если вы используете такой язык, как Perl, и, в частности, если ваше ложное условие является либо ошибочным условием, либо наиболее распространенным условием, вы можете использовать структуру «never», которая выполняет блок кода. если условие не является истинным (то есть противоположно, если):

unless ($foo) {
    $bar;
}
1 голос
/ 03 октября 2008

Предсказание ветви Intel Pentium предварительно выбирает инструкции для случая «если». Если вместо этого он следует ветке "else": он очищает конвейер команд, вызывая остановку.

Если вас очень волнует производительность: укажите наиболее вероятный результат в предложении «если».

Лично я пишу это как

if (expected)
{
   //expected path
}
else
{
   //fallback other odd case
} 
1 голос
/ 03 октября 2008

Обычно вы можете сделать условие положительным, не переключаясь вокруг блоков if / else.

Изменить

   if (!widget.enabled()) {
     // more common 
   } else {
     // less common 
   }

до

   if (widget.disabled()) {
     // more common 
   } else {
     // less common
   }
1 голос
/ 03 октября 2008

Для меня это зависит от состояния, например:

if (!PreserveData.Checked)
{  resetfields();}

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

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

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

Итак, давайте предположим, что должно быть предложение "else".

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

  1. Чем короче первый блок (блок if), тем легче понять всю конструкцию if-else. Когда блок «если» достаточно длинный, становится слишком просто упускать из виду существование блока «еще».

  2. Когда пути «if» и «else» логически асимметричны (например, «обычная обработка» или «обработка ошибок»), в автономной конструкции «if-else» это делает не имеет большого значения, какой путь первый, а какой второй. Однако, когда есть множественные конструкции if-else в непосредственной близости друг к другу (включая вложение), и когда все эти конструкции if-else имеют асимметрию одного и того же вида - тогда это очень важно организовать эти асимметричные пути последовательно.

    Опять же, это может быть "если ... нормальный путь ... еще ... ненормальный путь" для всех или "если ... ненормальный путь ... еще ... нормальный путь" для всех, но это не должно быть сочетание этих двух вариантов.

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

  3. Выражение, которое начинается с отрицания, обычно менее читабельно / понятно, чем выражение, которое этого не делает.

Итак, у нас есть эти три конкурирующих требования / правила, и реальный вопрос: какие из них важнее других. Для Аллена Голуба правило № 1, пожалуй, самое важное. Для Стива Макконнелла - это правило № 2. Но я не думаю, что вы действительно можете выбрать только одно из этих правил в качестве единой контрольной линии.

Могу поспорить, что вы уже догадались о моих личных приоритетах здесь (по тому, как я заказал правила выше :-).

Мои причины просты:

  • Правило № 1 является безусловным и его невозможно обойти. Если один из блоков настолько длинный, что выходит за пределы экрана, он должен стать «другим». (Нет, не рекомендуется создавать механическую функцию / метод просто для уменьшения количества строк в блоке «if» или «else»! Я предполагаю, что каждый блок уже имеет логически оправданную минимальное количество строк.)

  • Правило № 2 включает в себя множество условий: несколько конструкций if-else, все имеют асимметрию одинакового типа и т. Д. Поэтому оно просто не применяется во многих случаях.

    Кроме того, я часто наблюдаю следующее интересное явление: когда правило № 2 действительно применяется и когда оно используется должным образом, оно фактически не конфликтует с правилом № 1! Например, всякий раз, когда у меня есть куча операторов if-else с асимметрией «нормальный или ненормальный», все «ненормальные» пути короче, чем «нормальные» (или наоборот). Я не могу объяснить это явление, но думаю, что это просто признак хорошей организации кода. Другими словами, всякий раз, когда я вижу ситуацию, когда правила № 1 и № 2 находятся в конфликте, я начинаю искать «запахи кода» и чаще всего нахожу их; а после рефакторинга - тада! нет больше болезненного выбора между правилом № 1 и правилом № 2 :-)

  • Наконец, правило № 3 имеет наименьшую область действия и поэтому является наименее критичным.

    Кроме того, как отмечают здесь другие коллеги, часто очень легко «обмануть» это правило (например, написать «if (disabled) ,,,» вместо «if (! Enabled) ... «).

Я надеюсь, что кто-то может понять этот опус ...

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

Я ужасен, когда дело доходит до того, как я настраиваю операторы if. По сути, я настроил это на основе того, что именно ищу, что приводит к тому, что все будет по-другому.

if (userinput = null) {
explodeViolently ();
} else {
на самом деле делать вещи;
}

или что-то вроде

if (1 + 1 = 2) {
делать вещи;
} else {
explodeViolently ();
}

Какой раздел инструкции if / else действительно делает для меня вещи, это моя плохая привычка.

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

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

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

Я всегда держу наиболее вероятным первым.

В Perl у меня есть дополнительная структура управления, чтобы помочь с этим. Обратное значение if.

unless (alive) {
     go_to_heaven;
} else {
     say "MEDIC";
}
0 голосов
/ 03 октября 2008
  1. поставить общий путь первым
  2. превратить отрицательные проверки в положительные (!full == empty)
...