Правильный порядок для логики структуры управления (true / false, false / true)? - PullRequest
1 голос
/ 23 октября 2008

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

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

Было бы трудно приспособиться к этому «негативному» мнению, я предпочитаю более позитивный прогноз, предполагая, что все верно:)

Ответы [ 10 ]

13 голосов
/ 23 октября 2008

Прекрасно обсуждается только эта тема в McConnell Code Complete Это книга, которую я очень рекомендую. Во всяком случае, соответствующее обсуждение на страницах 706-708 первого издания или стр. 749-750 второго издания (спасибо плинтусу). Из этой книги:

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

6 голосов
/ 23 октября 2008

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

if( condition is true ) {
    do something small;
} else { 
    do something;
    and something else; 
    . . .
    and the 20th something;
}

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

if( variable is defined ) {
    if( variable == value ) {
        ...
    }
}

вместо этого:

if( (variable is defined) && (variable == value) ) {
     ...
}

Я не думаю, что есть "правильный" способ определить ваши условия. Если вы работаете в компании, которая имеет стандарты кодирования, вам следует проверить, включено ли это в стандарты. (В последнем месте, где я работал, было определено разумное количество стандартов, но не было указано, как писать условную логику.)

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

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

Таким образом, я могу генерировать исключения / прерывать операции, прежде чем начать «настройку» для нормального выполнения программы.

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

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

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

    if(arg == null){ 
      throw new IllegalArgumentException();  // harsh (correct)
    }
    // or 
    if(arg == null){
        arg = "";  // forgiving (lazy)
    }

Далее я пытаюсь проверять 1 условие только в каждом операторе if. вместо

    if(condition1 && condition2) {
        ...
    } else {
        ...
    }

я вообще предпочитаю

    if(condition1) {
        if(condition2) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }

Этот подход проще для установки точек останова и делает логику более очевидной.

Я избегаю отрицаний; вместо

    if(! condition) {
        ...a...
    } else {
        ...b...
    }

вещи лучше переставить на

    if(condition) {
        ...b...
    } else {
        ...a...
    }

Наконец, все методы, которые возвращают логический результат, должны иметь «положительное» имя, которое указывает, что означают результаты:

    boolean checkSomething(Something x){ ... }     // bad -- whats the result?
    boolean isSomethingInvalid(Something x){ ... } // better, but ...
    boolean isSomethingValid(Something x){ ... }   // best, no "mental negation"
2 голосов
/ 23 октября 2008

Я стремлюсь структурировать свои условия таким образом, чтобы минимизировать объем информации, которую должен воспринимать читатель. Иногда легче проверить, что отрицательное доказывает положительное:

Пример - тест, чтобы увидеть, пересекается ли период с 2 датами с другим периодом с 2 датами, легче написать как тест на отсутствие пересечения 2 периодов

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

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

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

(Контекст: Java)

READABILITY1: условие, которое разрешается в меньший блок кода, идет первым

if (condition) {
  smallBlock();
} else {
  bigBlockStart();
  ........
  bigBlockEnd();
}

READABILITY2: положительное утверждение идет первым, так как легче не заметить знак отрицания

MAKING SENSE: Утвердите все предварительные условия для метода с помощью Assert.blabla () и используйте условные выражения только для того, что метод делает.

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

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

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

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

Либо / Или. Я обычно использую «негативный» подход.

если (! Что-то) {

}

...