Подтвердить что ты не робот

Что положить в блок IF и что добавить в блок ELSE?

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

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

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

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

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

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

  • Держите условие положительным (меньше умственный расчет при чтении)
  • Поместите наиболее распространенный путь в первый блок
4b9b3361

Ответ 1

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

if (condition)
    return;

DoSomething();

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

Ответ 2

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

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

- Аллен Голуб, "Достаточно веревки, чтобы стрелять себе в ногу", p52

Поместите обычный случай после if, а не после else

- Стив Макконнелл, "Code Complete, 2nd ed.", p356

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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

  if (!some_function_that_could_fail())
  {
     // Error handling code
  }
  else
  {
     // Success code
  }

Ответ 6

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

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

if (somePositiveCondition)
else {
    //stuff
}

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

Ответ 7

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

if DataIsGood() then
   DoMyNormalStuff
else
   TakeEvasiveAction

Вместо обратного пути, который стремится выродиться в:

if SomeErrorTest then
  TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
  CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
  DoMoreErrorHandling
else
  DoMyNormalStuff

Ответ 8

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

Пример:

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

// do rest of code here...

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

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

Ответ 9

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

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

if (not_dead) {
} else {
}

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

if (alive) {
} else {
}

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

if (!alive) {
} else {
}

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

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

Что означает

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

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

Ответ 10

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

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

Как насчет ситуации, когда "общий" случай ничего не делает? Что тогда

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

Или вы это делаете?

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

"Всегда положительное" правило на самом деле не то, что вы хотите. Вы хотите посмотреть на правила, похожие на следующие.

  • Всегда естественный - он должен читаться как английский (или как бы там ни был общий язык в вашей организации).
  • По возможности, обычные случаи сначала - поэтому они кажутся обычными.
  • По возможности используйте положительную логику; отрицательная логика может использоваться там, где она обычно говорила так, или где общий случай - это ничего не делать.

Ответ 11

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

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

Ответ 12

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

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

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

Ответ 13

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

Измените

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

to

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

Ответ 14

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

Если вы заботитесь о производительности, поставьте наиболее вероятный результат в разделе "if".

Лично я пишу его как

if (expected)
{
   //expected path
}
else
{
   //fallback other odd case
} 

Ответ 15

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

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

unless ($foo) {
    $bar;
}

Ответ 16

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

Итак, допустим, что должно существовать предложение else.

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

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

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

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

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

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

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

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

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

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

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

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

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

    Кроме того, как это описано другими коллегами, часто очень легко "обманывать" это правило (например, писать "if (disabled)", "вместо" if (! enabled)... ").

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

Ответ 17

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

Ответ 18

  • сначала введите общий путь
  • превратить отрицательное cheking в положительные (!full == empty)

Ответ 19

Если у вас должно быть несколько точек выхода, сначала поставьте их и очистите:

if TerminatingCondition1 then
  Exit
if TerminatingCondition2 then
  Exit

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

if NormalThing then
  DoNormalThing
else
  DoAbnormalThing

Ответ 20

Я всегда придерживаюсь, скорее всего, первой.

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

unless (alive) {
     go_to_heaven;
} else {
     say "MEDIC";
}

Ответ 21

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

Ответ 22

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

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

или, возможно, что-то вроде
если (1 + 1 = 2) { делать вещи,
} else {
explodeViolently();
}

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

Ответ 23

Обычно я положил положительный результат (поэтому метод) в начале так:

if(condition)
{
doSomething();
}
else
{
System.out.println("condition not true")
}

Но если условие должно быть ложным для используемого метода, я бы сделал следующее:

if(!condition)
{
doSomething();
}
else
{
System.out.println("condition true");
}