Почему утверждение «если» считается злом? - PullRequest
60 голосов
/ 12 октября 2009

Я только что пришел с Конференция по простому проектированию и тестированию . На одной из сессий мы говорили о злых ключевых словах в языках программирования. Кори Хейнс , который предложил тему, был убежден, что if утверждение является абсолютным злом. Его альтернативой было создание функций с предикатами 1007 *. Не могли бы вы объяснить мне, почему if является злом.

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

Ответы [ 18 ]

4 голосов
/ 12 октября 2009

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

3 голосов
/ 12 октября 2009

Единственная проблема с предикатами (с точки зрения замены if операторов) заключается в том, что вам все еще нужно проверять их:

function void Test(Predicate<int> pr, int num) 
{
    if (pr(num))
    { /* do something */ }
    else
    { /* do something else */ }
}

Конечно, вы можете использовать троичный оператор (?:), но это просто скрытый оператор if ...

2 голосов
/ 12 октября 2009

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

2 голосов
/ 03 февраля 2015

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

В основе этого лежит предпочтение полиморфизма if. Вместо:

if(animaltype = bird) {
     squawk();
} else if(animaltype = dog) {
     bark();
}

... использовать:

animal.makeSound();

Но это предполагает, что у вас есть класс / интерфейс Animal - так что в действительности if говорит вам, что вам нужно создать этот интерфейс.

Так в реальном мире, какого рода if s мы видим, которые приводят нас к решению полиморфизма?

if(logging) {
      log.write("Did something");
}

Это действительно раздражает видеть во всем вашем коде. Как насчет двух (или более) реализаций Logger?

this.logger = new NullLogger();    // logger.log() does nothing
this.logger = new StdOutLogger();  // logger.log() writes to stdout

Это приводит нас к шаблону стратегии .

Вместо:

if(user.getCreditRisk() > 50) {
     decision = thoroughCreditCheck();
} else if(user.getCreditRisk() > 20) {
     decision = mediumCreditCheck();
} else {
     decision = cursoryCreditCheck();
}

... вы могли бы иметь ...

decision = getCreditCheckStrategy(user.getCreditRisk()).decide();

Конечно, getCreditCheckStrategy() может содержать if - и это вполне может быть уместно. Вы толкнули его в аккуратное место, где оно принадлежит.

2 голосов
/ 12 октября 2009

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

1 голос
/ 25 июня 2012

Я думаю, что если заявления являются злом, но если выражения не являются. То, что я подразумеваю под выражением if, в этом случае может быть чем-то вроде троичного оператора C # (условие? TrueExpression: falseExpression). Это не зло, потому что это чистая функция (в математическом смысле). Он оценивает новое значение, но не влияет ни на что другое. Из-за этого он работает в модели замещения.

Императив Если заявления являются злом, потому что они заставляют вас создавать побочные эффекты, когда вам это не нужно. Чтобы оператор If имел смысл, вы должны создавать разные «эффекты» в зависимости от выражения условия. Этими эффектами могут быть такие вещи, как ввод-вывод, графический рендеринг или транзакции с базой данных, которые изменяют вещи вне программы. Или это могут быть операторы присваивания, которые изменяют состояние существующих переменных. Обычно лучше минимизировать эти эффекты и отделить их от реальной логики. Но благодаря операторам If мы можем свободно добавлять эти «условно исполняемые эффекты» повсюду в коде. Я думаю, что это плохо.

0 голосов
/ 07 февраля 2013

Если не зло! Считай ...

int sum(int a, int b) {
    return a + b;
}

Скучно, а? Теперь с добавлением, если ...

int sum(int a, int b) {
    if (a == 0 && b == 0) {
        return 0;
    }
    return a + b;
}

... ваша производительность создания кода (измеряется в LOC) удваивается.

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

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

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

int sum(int a, int b) {
    if (a == 0 || b == 0) {
        return 0;
    }
    return a + b;
}

Сколько бы еще нужно было изменить код, если бы вы не изобрели if с самого начала.

Благодарность будет вашей со всех сторон.

Заключение: никогда не бывает достаточно, если.

Вот, пожалуйста. К.

0 голосов
/ 12 октября 2009

Хорошо, что в ruby ​​ у нас есть , если ;)

Но если серьезно, то , если - следующий goto , что даже если большинство людей думает, что это зло, в некоторых случаях это упрощает / ускоряет вещи (а в некоторых случаях как низкоуровневый высокооптимизированный код, это обязательно).

...