Если-меньше программирования (в основном без условных обозначений)


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

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

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

Я нашел один вопрос, так что это было связано, но я не знаком с C++, поэтому я не понимаю слишком много ответов там.

(Я не ОО гуру кстати, но я могу управлять)

Я самый опытный в PHP, а после этого Python поэтому я бы предпочел информацию, которая использует эти языки.

Update: я попрошу своего коллегу получить дополнительную информацию о том, что он имел в виду.

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

6 58

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

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