Почему, 'если' оператор рассмотрел зло?

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

Другой популярный подход должен обернуть контейнерный экземпляр со статическим классом и использованием что статический класс для доступа к Вашему (одиночный элемент) контейнер. Можно найти пример этого в библиотеке Commons Носорога Ayende здесь . Этот подход однако имеет серьезные недостатки и должен избежаться.

63
задан skaffman 20 March 2012 в 14:20
поделиться

15 ответов

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

Есть случаев, когда вполне разумно использовать if

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

// this is a good "if" use-case
int Min(int a, int b)
{
    if (a < b) 
       return a;
    else
       return b;
}

// or, if you prefer the ternary operator
int Min(int a, int b)
{
    return (a < b) ? a : b;
}

Переход по «типу кода» - это запах кода

С другой стороны, если вы столкнетесь с кодом который проверяет какой-то код типа, или проверяет, относится ли переменная к определенному типу, тогда это, скорее всего, хороший кандидат для рефакторинга, а именно замены условного выражения на полиморфизм .

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

Примите во внимание:

// this is called branching on a "type code",
// and screams for refactoring
void RunVehicle(Vehicle vehicle)
{
    // how the hell do I even test this?
    if (vehicle.Type == CAR)
        Drive(vehicle);
    else if (vehicle.Type == PLANE)
        Fly(vehicle);
    else
        Sail(vehicle);
}

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

// adding a new vehicle is gonna be a piece of cake
interface IVehicle
{
    void Run();
}

// your method now doesn't care about which vehicle 
// it got as a parameter
void RunVehicle(IVehicle vehicle)
{
    vehicle.Run();
}

И теперь вы можете легко протестировать если ваш метод RunVehicle работает должным образом:

// you can now create test (mock) implementations
// since you're passing it as an interface
var mock = new Mock<IVehicle>();

// run the client method
something.RunVehicle(mock.Object);

// check if Run() was invoked
mock.Verify(m => m.Run(), Times.Once());

Шаблоны, которые отличаются только своими , если условия могут быть повторно использованы

Относительно аргумента о замене if с «предикатом» в вашем вопросе Хейнс, вероятно, хотел упомянуть, что иногда в вашем коде существуют похожие шаблоны, которые отличаются только своими условными выражениями. Условные выражения действительно появляются вместе с if s, но вся идея состоит в том, чтобы выделить повторяющийся шаблон в отдельный метод, оставив выражение в качестве параметра. s написаны внутри метода расширения LINQ Where , который был протестирован и закрыт для модификации. Меньше собственного кода - это всегда хорошо: меньше вещей для тестирования, меньше проблем, которые могут пойти не так, а код проще отслеживать, анализировать и поддерживать.

Рефакторинг, когда вы чувствуете запах кода, но не делайте этого. t over-engineering

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

Меньше собственного кода - это всегда хорошо: меньше вещей, которые нужно тестировать, меньше вещей, которые могут пойти не так, а код проще отслеживать, анализировать и поддерживать.

Рефакторинг, когда вы чувствуете запах кода, но не делайте этого. t over-engineering

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

Меньше собственного кода - это всегда хорошо: меньше вещей, которые нужно тестировать, меньше вещей, которые могут пойти не так, а код проще отслеживать, анализировать и поддерживать.

Рефакторинг, когда вы чувствуете запах кода, но не делайте этого. t over-engineering

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

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

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

76
ответ дан 24 November 2019 в 16:02
поделиться

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

2
ответ дан 24 November 2019 в 16:02
поделиться

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

2
ответ дан 24 November 2019 в 16:02
поделиться

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

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

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

3
ответ дан 24 November 2019 в 16:02
поделиться

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

4
ответ дан 24 November 2019 в 16:02
поделиться

Предикаты исходят из логических / декларативных языков программирования, таких как PROLOG. Для определенных классов проблем, таких как решение ограничений, они, вероятно, лучше, чем множество растянутых пошаговых инструкций «если-сделай-то-то-сделай-это». Проблемы, которые было бы сложно решить в императивных языках, можно решить всего несколькими строками в PROLOG.

Также существует проблема масштабируемого программирования (из-за перехода к многоядерности, сети и т. Д.). Операторы If и императивное программирование в целом имеют тенденцию быть в пошаговом порядке и не масштабируемы. Однако логические объявления и лямбда-исчисление, опишите, как можно решить проблему и на какие части ее можно разбить. В результате интерпретатор / процессор, выполняющий этот код, может эффективно разбивать код на части и распределять его по нескольким процессорам / ядрам / потокам / серверам.

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

4
ответ дан 24 November 2019 в 16:02
поделиться

Я с вами согласен; он был неправ . Вы можете зайти слишком далеко с подобными вещами, слишком умно для вашего же блага.

Код, созданный с использованием предикатов, а не «если», было бы ужасно поддерживать и тестировать.

7
ответ дан 24 November 2019 в 16:02
поделиться

Хорошо, что в рубине у нас есть , кроме ;)

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

0
ответ дан 24 November 2019 в 16:02
поделиться

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

Например, комментарии перечислены как запах кода Мартином Фаулером, но я бы не стал воспринимать всерьез тех, кто говорит, что «комментарии - это зло. ; не используйте их ".

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

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

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

8
ответ дан 24 November 2019 в 16:02
поделиться

Также как в стихе из Библии о деньгах, если утверждения не являются злом - ЛЮБОВЬ утверждений «если» является злом. Программа без операторов if - нелепая идея, и использование их по мере необходимости необходимо. Но программа, в которой есть 100 блоков if-else if подряд (что, к сожалению, я видел), определенно является злом.

9
ответ дан 24 November 2019 в 16:02
поделиться

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

Мистер. Хейнс ведет себя глупо, и над ним следует посмеяться.

10
ответ дан 24 November 2019 в 16:02
поделиться

Я думаю, что это зависит от того, что вы делаете, если честно.

Если у вас есть простой оператор if..else , зачем использовать предикат ?

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

Этот парень, кажется, был немного педантичен на мой вкус. Замена всех if на Predicates - просто бред.

17
ответ дан 24 November 2019 в 16:02
поделиться

Есть кампания Anti-If , которая началась ранее в этом году. Основная предпосылка состоит в том, что многие вложенные операторы if часто могут быть заменены полиморфизмом.

Мне было бы интересно увидеть вместо этого пример использования предиката. Это больше похоже на функциональное программирование?

14
ответ дан 24 November 2019 в 16:02
поделиться

Есть еще один смысл, в котором if может быть злым: когда он появляется вместо полиморфизма.

Например,

 if (animal.isFrog()) croak(animal)
 else if (animal.isDog()) bark(animal)
 else if (animal.isLion()) roar(animal)

вместо

 animal.emitSound()

Но в основном если это совершенно приемлемый инструмент для того, что он делает. Конечно, им можно злоупотреблять и злоупотреблять, но он далек от статуса goto.

84
ответ дан 24 November 2019 в 16:02
поделиться

Хорошая цитата из Code Complete:

Кодируйте, как если бы тот, кто поддерживает вашу программу, был жестоким психопатом, который знает, где вы живете.
- Аноним

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

32
ответ дан 24 November 2019 в 16:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: