Если-меньше программирования (в основном без условных обозначений)
У меня был коллега, который сказал мне, что он когда-то работал в компании, у которой в качестве политики никогда не было условных выражений ("если" и "переключить") в коде, и что они позволяют всем решениям в коде выполняться с использованием полиморфизма и (я предполагаю) некоторых других принципов OO.
Я вроде понять причины этого, имея код, который является более сухим и легче обновить, но я ищу более глубокое объяснение этой концепции. Или, может быть, это часть более общего подхода к проектированию.
Если у кого-то есть какие-либо ресурсы для этого или были бы готовы объяснить или даже иметь еще несколько терминов, связанных с этим, я могу использовать, чтобы найти больше ответов, я был бы очень обязан.
Я нашел один вопрос, так что это было связано, но я не знаком с C++, поэтому я не понимаю слишком много ответов там.
(Я не ОО гуру кстати, но я могу управлять)
Я самый опытный в PHP, а после этого Python поэтому я бы предпочел информацию, которая использует эти языки.
Update: я попрошу своего коллегу получить дополнительную информацию о том, что он имел в виду.
обновление 2015: после еще нескольких лет опыта в программировании я вижу теперь, что цель этой политики, вероятно, заключалась в том, чтобы предотвратить добавление программистами функциональности случайным образом, просто добавив условные выражения (if-операторы) в определенных местах. Лучший способ расширить программное обеспечение-использовать "открытый/закрытый принцип" где программное обеспечение расширяется с помощью наследования и полиморфизма. Я сильно сомневаюсь, что политика была очень строгой по всем условностям, так как без них трудно полностью обойтись.
6 ответов:
есть некоторые ресурсы на кампания против IF сайта, например,в этой статье.
Я считаю, что это вопрос степени. Условные обозначения не всегда плохи, но ими можно злоупотреблять (и часто злоупотребляют).
дополнительные мысли (один день спустя)
рефакторинг: улучшение дизайна существующего кода хорошая ссылка на эту тему (и многие другие). Он охватывает Заменить Условное с полиморфизмом. Есть и новый,заменить условный посетитель, на веб-сайте.
Я ценю простоту и единая ответственность за удаление всех
if
заявления. Эти три цели часто совпадают. Инструменты статического анализа, которые поддерживают цикломатическая сложность метрика может быстро указать код с вложенными или последовательными условными обозначениями. Элементif
операторы могут оставаться после рефакторинга, но могут быть разбиты в меньшие методы и / или несколько классов.обновление: Майкл перья написал статью о Безусловного Программирования.
Это популярная тема: Фил Хаак на смерть утверждению IF!
после нескольких лет программирования я возвращаюсь к своему собственному вопросу, контекст которого я теперь понимаю немного лучше.
есть хороший разговор с Санди Мец, где она переделывает волосатого шара если-заявления на то, что менее волосатый: https://www.youtube.com/watch?v=8bZh5LMaSmE
Я прочитал сообщение, которое вы связали, и кажется, что они в основном говорили об устранении необходимости в условных обозначениях в классе, не путать со всем кодом в целом. Идея заключается в том, что если вам нужно проверить состояние объекта (используя условное), чтобы определить, имеет ли он определенную функциональность, то на самом деле у вас есть два объекта (один, который поддерживает функциональность, а другой-нет) и вместо этого следует определить их как два связанных класса.
у меня был коллега, который сказал мне, что он когда-то работал в компании, которая как политики не имеют условные ("если" и "переключатель" заявления) в коде и что они позволяют принимать все решения в код должен быть выполнен с использованием полиморфизма и (я предполагаю) некоторых других OO принципы.
Я думаю, что ваш коллега неправильно понял что-то или использовал неправильные слова, чтобы объяснить это. И вы не можете полностью избежать условных утверждений.
есть дело в том, что пролиферация операторов if внутри ООП может быть симптомом плохого программирования. Вот пример:
Не используйте if для проверки возвращаемого значения функции, как старое программирование в стиле C:
int ret = some_func(); if (ret != null) //do something
Это было типично в коде C, но с ООП вы должны использовать исключение:
try{ do_something(); }catch(Exception e){ e.printStackTrace(); //why I was not able to do something handle(e); //there is something else I could do to handle the occurred error }
иногда, если распространение заявлений связано с плохим дизайном. Рассмотрим следующий пример в Java:
BaseClass base; if (base instanceof DerivedClassOneFromBase){ DerivedClassOneFromBase d = (DerivedClassOneFromBase)base; d.methodOne(); }else if (base instanceof DerivedClassOneFromBase){ DerivedClassTwoFromBase d = (DerivedClassTwoFromBase)base; d.methodTwo(); }
Это еще один пример плохо, если заявления, вероятно, связаны с плохим дизайном. Если два производных объекта будут иметь общий метод, определенный в их базовом классе BaseClass, вы могли бы вызвать этот метод вместо проверки их конкретного типа и приведения их:
base.commonMethod();
иногда условные обозначения внутри методов плохи, поскольку они являются признаком того, что вы просто выполняете несколько функций или методов нескольких типов в одном методе.
Если у вас есть класс под названием Автомобиль и подклассы, такие как автомобиль и велосипед, и такой метод, как:
drive(Automobile a) if (a.isCar) // do stuff else if (a.isBike) // do stuff
вы, скорее всего, делаете что-то не так. Даже если это не переключатель, основанный на типе, он часто может быть неправильным. Если метод выполняет несколько функций в зависимости от некоторой переменной, то часто пытаются сделать более одной вещи и, вероятно, должны быть разделены на несколько методов.
например:
save(Car c) if (c is new) // do some stuff else if (c is old) // do some stuff
потенциально могут быть разбиты на сохранение и обновление, так как они являются двумя различными функциями. Хотя это действительно зависит.
полностью запрещая, если заявления были бы глупыми, хотя, поскольку у них есть много допустимых случаев использования.
избегание условных обозначений не обязательно означает, что вам нужно сделать это с помощью полиморфизма или наследования, например :
У вас есть 3 разных папки для хранения загруженных изображений, загруженных видео и загруженных pdf
вы можете написать код как:
uploadMedia(mediaType){ if(mediaType == images){ uploadTo("myProject/images"); }else if(mediaType == videos){ upoloadTo("myProject/videos); }else if(mediaType == pdf){ uploadTo("myProject/pdf"); } }
Другой альтернативой, которую люди могут использовать, является switch-case:
uploadMedia(mediaType){ switch(mediaType){ case : images uploadTo("myProject/images"); break; case : videos uploadTo("myProject/videos"); break; case : pdf uploadTo("myProject/pdf"); break; } }
но тогда вы можете полностью избежать условного оператора, используя что-то вроде dictionary/hashmap/json (В зависимости от того, с чем вы работаете) :
например :
HashMap<String,String> mediaMap = new HashMap<>(); mediaMap.put("images","myProject/images"); mediaMap.put("videos","myProject/videos"); mediaMap.put("pdf","myProject/pdf"); //mediaType can be images/videos/pdf same as keys of mediaMap uploadMedia(mediaType){ uploadTo(mediaMap.get(mediaType)); }
Это своего рода псевдокод, поэтому могут быть синтаксические ошибки, но в целом эта концепция также полезна во избежание условных обозначений. Также строка кода может быть уменьшена.