If-less программирование (в основном без условий)
У меня был коллега, который сказал мне, что он когда-то работал в компании, у которой в качестве политики никогда не было условий ("если" и "переключить" заявления) в коде, и что они позволяют всем решениям в коде делать с использованием полиморфизма и (я предполагаю) некоторые другие принципы OO.
Я вроде понять причины этого, имея код, который более сухой и легче обновлять, но я ищу более глубокое объяснение этой концепции. Или, может быть, это часть более общего подхода к проектированию.
Если у кого-то есть какие-либо ресурсы для этого или будет готов объяснить или даже иметь еще несколько терминов, связанных с этим, я могу использовать, чтобы найти больше ответов, я был бы очень обязан.
нашел один вопрос на SO это было связано, но я не знаком с C++, поэтому я не понимаю слишком много ответов там.
(Я не ОО гуру кстати, но я могу управлять)
Я самый опытный в PHP, и после этого Python, поэтому я бы предпочел информацию, которая использует эти языки.
Update: я попрошу своего коллегу больше информации о том, что он имел в виду.
Update 2015: после нескольких лет опыта в программировании теперь я вижу, что цель этой политики, вероятно, заключалась в том, чтобы предотвратить добавление программистами функциональности случайным образом, просто добавив условные обозначения (операторы if) в определенных местах. Лучший способ расширить программное обеспечение-использовать "Открыто/Закрыто принцип" где программное обеспечение расширяется с помощью наследования и полиморфизма. Я сильно сомневаюсь, была ли политика супер строгой по всем условностям, так как без них трудно полностью обойтись.
6 ответов
есть некоторые ресурсы на кампания против IF сайта, например,в этой статье.
Я считаю, что это вопрос степени. Условные обозначения не всегда плохие, но ими можно злоупотреблять (и часто злоупотребляют).
дополнительные мысли (один день спустя)
рефакторинг: улучшение дизайна существующего кода хорошая ссылка на эту тему (и многие другие). Он охватывает Заменить Условное с полиморфизмом. Есть и новый,заменить условное на посетитель, на веб-сайте.
Я ценю простоту и единая ответственность за удаление всех if
заявления. Эти три цели часто совпадают. Инструменты статического анализа, поддерживающие цикломатическая сложность метрика может быстро указать код с вложенными или последовательными условными обозначениями. The if
операторы могут оставаться после рефакторинга, но могут быть разорваны в меньшие методы и / или несколько классов.
обновление: Майкл перья написал статью о Безусловного Программирования.
Это популярная тема: Фил Хаак на смерть заявлению IF!
после нескольких лет программирования я возвращаюсь к своему собственному вопросу, контекст которого я теперь понимаю немного лучше.
есть хороший разговор Сэнди Мец, где она рефакторирует действительно волосатый шар if-заявлений к чему-то waaay менее волосатому:https://www.youtube.com/watch?v=8bZh5LMaSmE
Я прочитал сообщение, которое вы связали, и кажется, что они в основном говорили об устранении необходимости в conditionals в классе, не путать со всем кодом в целом. Идея заключается в том, что если вам нужно проверить состояние объекта (используя условие), чтобы определить, имеет ли он определенную функциональность, то на самом деле у вас есть два объекта (один, который поддерживает функциональность, а другой-нет) и должен определить их как два связанных класса.
у меня был коллега, который сказал мне, что однажды он работал в компании, которая имел в качестве политики никогда не иметь conditionals ("if "и" switch" заявления) в кодексе и что они позволяют все решения в код будет выполнен с использованием полиморфизма и (я предполагаю) некоторых других 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));
}
это псевдо-код, поэтому могут быть синтаксические ошибки, но в целом эта концепция также полезны в предотвращении условные. Также строку кода можно уменьшить.