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));
}

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