Делает любой не соглашается с оператором: “использование переключателя является плохим стилем ООП”?

Вы явно не выглядели очень сложно:

Взято непосредственно с кода обработки PHPExcel Date:

public static function ExcelToPHP($dateValue = 0) {
    if (self::$ExcelBaseDate == self::CALENDAR_WINDOWS_1900) {
        $myExcelBaseDate = 25569;
        //    Adjust for the spurious 29-Feb-1900 (Day 60)
        if ($dateValue < 60) {
            --$myExcelBaseDate;
        }
    } else {
        $myExcelBaseDate = 24107;
    }

    // Perform conversion
    if ($dateValue >= 1) {
        $utcDays = $dateValue - $myExcelBaseDate;
        $returnValue = round($utcDays * 86400);
        if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) {
            $returnValue = (integer) $returnValue;
        }
    } else {
        $hours = round($dateValue * 24);
        $mins = round($dateValue * 1440) - round($hours * 60);
        $secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60);
        $returnValue = (integer) gmmktime($hours, $mins, $secs);
    }

    // Return
    return $returnValue;
}    //    function ExcelToPHP()

Установите self :: $ ExcelBaseDate == self :: CALENDAR_WINDOWS_1900 если необходимо указать используемый вами календарь базы данных Excel: Windows 1900 или Mac 1904

, и если вы хотите вместо него использовать PHP DateTime:

public static function ExcelToPHPObject($dateValue = 0) {
    $dateTime = self::ExcelToPHP($dateValue);
    $days = floor($dateTime / 86400);
    $time = round((($dateTime / 86400) - $days) * 86400);
    $hours = round($time / 3600);
    $minutes = round($time / 60) - ($hours * 60);
    $seconds = round($time) - ($hours * 3600) - ($minutes * 60);

    $dateObj = date_create('1-Jan-1970+'.$days.' days');
    $dateObj->setTime($hours,$minutes,$seconds);

    return $dateObj;
}    //    function ExcelToPHPObject()
26
задан IAdapter 16 February 2009 в 08:18
поделиться

22 ответа

Взятие Вашего продолжения:

, Что, если это - просто "investibility" логика для клиента, желающего бизнес-кредита. Возможно, innvestibility решение клиента для другого продукта действительно очень отличается... Кроме того, что, если существуют новые продукты, выходящие все время, каждый с различными investibility решениями и я не хочу обновлять свой базовый Клиентский класс каждый раз, когда это происходит?

и один из Ваших комментариев:

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

Вы правы, насколько это идет.

boolean investable = customer.isInvestable();

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

, Учитывая дополнительную информацию, теперь доступную, лучшее решение, казалось бы, было бы

boolean investable = product.isInvestable(customer);

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

В конкретном примере, если, тем не менее, я испытал бы желание сделать что-то как:

if (customer.getCategory() < PRIME) {
    investable = customer.getSavingsAccount().getBalance() > 1e6;
} else {
    investable = customer.isCeo();
}

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

17
ответ дан Dave Sherohman 15 October 2019 в 06:47
поделиться

Операторы выбора могут почти всегда заменяться полиморфизмом

И также

boolean investable = customer.isInvestable();

, Так как вызов к isInvestable является полиморфным, фактический алгоритм, используемый для совершения вызова, определяется типом клиента.

я думаю, что Вы оба неправы . Что, если это - просто "investibility" логика для клиента, желающего бизнес-кредита. Возможно, innvestibility решение клиента для другого продукта действительно очень отличается, и возможно не на основе "категории", но где они живут, женаты ли они, в каком секторе задания они работают?

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

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

0
ответ дан oxbow_lakes 15 October 2019 в 06:47
поделиться

Да, я сыт по горло людьми, говорящими Вам, это - плохой стиль.

Редактирование: Это имело больше смысла, прежде чем вопрос был зафиксирован.

1
ответ дан patros 15 October 2019 в 06:47
поделиться

"Кроме того, что, если существуют новые продукты, выходящие все время, каждый с различными investibility решениями и я не хочу обновлять свой базовый Клиентский класс каждый раз, когда это происходит?"

Это приходит на ум:

interface Investable
{
    boolean isIvestible(Customer c);
}

class FooInvestible 
    implements Investible
{
    public boolean isInvestible(final Customer c)
    {
        // whatever logic, be it switch or other things
    }
}

"проблема" с исходным использованием swtich и добавлением новых типов решений состоит в том, что Вы, вероятно, волнуете с некоторым огромным вложенным множеством крыс кода, который невозможно поддержать нормальным способом. Разделение решений в классы вынуждает принятие решений быть разделенным. Затем даже при использовании переключателя код, вероятно, останется более нормальным и удобным в сопровождении.

0
ответ дан TofuBeer 15 October 2019 в 06:47
поделиться

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

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

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

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

1
ответ дан Steve Mitcham 15 October 2019 в 06:47
поделиться

И теперь что? Несомненно, существует хорошее ООП способ сделать это:

str.request (это);

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

Когда-нибудь попытка методы расширения C#? Строка может быть расширена.

1
ответ дан 15 October 2019 в 06:47
поделиться

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

Кроме того, ООП не является серебряной пулей. Существуют времена, это - ответ, существуют времена, которые это не.

2
ответ дан Loren Pechtel 15 October 2019 в 06:47
поделиться

Я думаю, является ли оператор переключения плохой практикой ООП, зависит от того, где Вы используете оператор переключения.

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

При большинстве обстоятельств, хотя, я думаю, переключатели являются просто дизайном. Довольно часто сокрытие операционной сложности в различных объектах с тем же методом приводит к более понятному и возможно еще более быстрому коду. Например, если у Вас есть переключатель, который выполняется , партия затем предварительно упаковывавший объекты могла на самом деле сохранить некоторые циклы ЦП.

2
ответ дан Jeffrey Cameron 15 October 2019 в 06:47
поделиться

Я ничего не нахожу неправильно с использованием оператора переключения в коде OO. Моя единственная критика состоит в том, что я сделал бы новый метод на Клиенте под названием IsInvestible, который скрыл эту логику. Существует 0 неправильно с использованием оператора переключения как внутренняя реализация этого метода. Поскольку Вы сказали, что не можете добавить методы к перечислению, но можно добавить больше методов к Клиенту.

В случае у Вас нет доступа к источнику, я сказал бы, что non-instnance метод прекрасен. Самое чистое ООП потребовало бы совершенно нового объекта, но это кажется, что может быть излишество в этом случае.

2
ответ дан JaredPar 15 October 2019 в 06:47
поделиться

Я действительно полагаю, что включение типа является запахом кода. Однако я разделяю Ваше беспокойство о разделении проблем в коде. Но они могут быть решены во многих отношениях, которые позволяют Вам все еще использовать полиморфизм, например, шаблон "посетитель" или что-то подобное. Читайте на "Шаблоны разработки" Бандой Четыре.

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

    interface Operation {
      void handlePrimeCustomer(PrimeCustomer customer);
      void  handleMidPrimeCustomer(MidPrimeCustomer customer);
      void  handleSubPrimeCustomer(SubPrimeCustomer customer);    
    };

    class InvestibleOperation : public Operation {
      void  handlePrimeCustomer(PrimeCustomer customer) {
        bool investible = customer.isCeo();
      }

      void  handleMidPrimeCustomer(MidPrimeCustomer customer) {
        handleSubPrimeCustomer(customer);
      }

      void  handleSubPrimeCustomer(SubPrimeCustomer customer) {
        bool investible = customer.getSavingsAccount().getBalance() > 1e6;    
      }
    };

    class SubPrimeCustomer : public Customer {
      void  doOperation(Operation op) {
        op.handleSubPrimeCustomer(this);
      }
    };

   class PrimeCustomer : public Customer {
      void  doOperation(Operation op) {
        op.handlePrimeCustomer(this);
      }
    };

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

5
ответ дан Erik Engheim 15 October 2019 в 06:47
поделиться

ГЋ знают, куда Вы происходите из. Некоторые языки вынуждают Вас сделать это.

String str = getStr();
switch(str) {
case "POST" : this.doPost(); break;
case "GET" : this.doGet(); break;
//and the other http instructions
}

И теперь что? Несомненно, существует хорошее ООП способ сделать это:

str.request(this);

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

Это не хорошее ООП, это наверняка, но хороший код не всегда... возможно.

Позволяют мне disgress на мгновение. Я пишу свой тезис. Мне лично не нравится обычная установка рекурсивных функций. Вы обычно имеете как funcRec (arg1, аргумент), и func (arg1): =func (funcRec (arg1,0));

, таким образом, я определил его в своем тезисе с параметрами по умолчанию. Не все знают понятие параметра по умолчанию. Мой псевдокод использования тезиса, но преподаватель сделал, чтобы я изменил алгоритм на традиционный путь, потому что Вы не сталкиваетесь с параметрами по умолчанию очень часто, не используйте их. Не удивляйте своего читателя излишне. Я думаю, что он прав.

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

Так, нижняя строка: Истинно красивые программы требуют превосходных библиотек, превосходных браузеров кода и инструментов, bugtrackers qualitiy FogBugz, по крайней мере, лучше более интегрированное, управление версиями качества мерзавца, и т.д. И, umm, люди вокруг Вас, кто может использовать все эти вещи и знать, как обработать все эти вещи. И больше всего: beaauuuuutiful язык, который позволяет изящные решения хитрых проблем.

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

И теперь находят компромисс.

Это печально, я знаю.

2
ответ дан nes1983 15 October 2019 в 06:47
поделиться

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

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

5
ответ дан Ryan Emerle 15 October 2019 в 06:47
поделиться

Я просматриваю операторы переключения как более читаемую альтернативу если/еще блоки.

я нахожу, что, если можно свести логику к структуре, которая может быть оценена целиком, код, вероятно, будет обеспечивать уровень инкапсуляции, которая требуется в ООП.

В какой-то момент реальная (грязная) логика должна быть записана, чтобы практическая программа поставлялась. Java и C# не являются строго языками ООП, учитывая, что они наследовались C. Если Вы захотите осуществить строго код ООП, то необходимо будет использовать язык, который не обеспечивает идиомы, которые нарушают то мышление. Мое представление состоит в том, что и Java и C# предназначаются, чтобы быть гибкими.

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

3
ответ дан EnocNRoll - Ananda Gopal 15 October 2019 в 06:47
поделиться

Статья Robert Martin о Открывает, Closed Principle обеспечивает другую точку зрения:

ОБЪЕКТЫ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ (КЛАССЫ, МОДУЛИ, ФУНКЦИИ, ETC.) ДОЛЖНО БЫТЬ ОТКРЫТО ДЛЯ РАСШИРЕНИЯ, НО ЗАКРЫТЫЙ ДЛЯ МОДИФИКАЦИИ.

В Вашем примере кода, Вы эффективно включаете клиента 'Тип Категории'

boolean investible ;
switch (customer.getCategory()) {
    case SUB_PRIME:
    case MID_PRIME:
        investible = customer.getSavingsAccount().getBalance() > 1e6; break;
    case PRIME:
        investible = customer.isCeo(); break;
}

В этой нынешней обстановке, новые клиентские категории могли бы возникать ;-). Это означает иметь необходимость открыть этот класс и постоянно изменять его. Могло бы быть хорошо, если у Вас только есть единственный оператор переключения, но что происходит, если Вы хотите использовать подобную логику в другом месте.

, А не другие предложения, где isInvestible сделан методом на Customer, я сказал бы, что Cagtegory должен стать абсолютным классом, и используемый для того, чтобы принять эти решения:

boolean investible ;
CustomerCategory category = customer.getCategory();
investible = category.isInvestible(customer);

class PrimeCustomerCategory extends CustomerCategory {
    public boolean isInvestible(Customer customer) {
        return customer.isCeo();
    }
}
6
ответ дан toolkit 15 October 2019 в 06:47
поделиться

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

12
ответ дан Jim Arnold 15 October 2019 в 06:47
поделиться

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

, Таким образом, я повторно сформулирую quesion к: "Переключатель действительно ли использования является знаком плохого кода?" , потому что это действительно, о чем я забочусь. Теперь я продолжу отвечать на это.

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

Один последний комментарий: "Используя [функция языка X] во всем плоха", опасно близко к "Разработчикам языка, были глупы включать [функцию языка X] в нем".

1
ответ дан Daniel Daranas 15 October 2019 в 06:47
поделиться

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

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

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

7
ответ дан snarf 15 October 2019 в 06:47
поделиться

Это - плохой стиль ООП.

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

14
ответ дан Pete Kirkham 15 October 2019 в 06:47
поделиться

Операторы выбора могут почти всегда заменяться полиморфизмом.

public class NormalCustomer extends Customer {
    public boolean isInvestible() {
        return getSavingsAccount().getBalance() > 1e6;
    }
}

public class PreferredCustomer extends Customer {
    public boolean isInvestible() {
        return isCeo();
    }
}

Этот подход упростит клиентский код. Клиентский код не должен знать детали того, как "investibility" вычисляется, и он больше не должен повреждаться Закон Demeter путем рытья в состояние Клиентского объекта.

1
ответ дан hallidave 15 October 2019 в 06:47
поделиться

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

2
ответ дан jrockway 15 October 2019 в 06:47
поделиться

Я думаю, что операторы как

Используя оператор переключения являются плохим стилем ООП.

и

Операторы выбора могут почти всегда заменяться полиморфизмом.

упрощают. Истина - то, что операторы выбора, которые включают тип , являются плохим стилем ООП. Они - те, Вы хотите заменить полиморфизмом. При включении значение прекрасно.

56
ответ дан Bill the Lizard 15 October 2019 в 06:47
поделиться

Переключатели являются запахом кода при использовании в чистом коде OO. Это не означает, что они неправы по определению, просто что необходимо думать дважды об использовании их. Будьте дополнительны осторожный.

Мое определение переключателя здесь также включает if-then-else операторы, которые могут легко быть переписаны как операторы переключения.

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

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

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

int dbValue = ...;

switch (dbValue)
{
  case 0: return new DogBehaviour();
  case 1: return new CatBehaviour();
  ...
  default: throw new IllegalArgumentException("cannot convert into behaviour:" + dbValue);  
}

РЕДАКТИРОВАНИЕ после чтения некоторых ответов.

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

Двойная отправка: полиморфизм дважды. Но Ваш класс посетителя является чрезвычайно все еще большим переключателем, и он имеет некоторые из тех же проблем, как объяснено выше.

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

Включение значения прекрасно: хорошо, но операторы переключения в большинстве случаев используются, чтобы протестировать на сингле int, char, enum... оценить, в противоположность if-then-else, где диапазоны и более экзотические условия могут быть протестированы. Но если мы диспетчеризируем на этом единственном значении, и это не в краю нашей модели OO, как объяснено выше, затем кажется, что переключатели часто используются для диспетчеризации на типе, а не на значении. Или: если Вы можете не , заменяют условную логику if-then-else переключателем, то Вы, вероятно, в порядке, еще Вы, вероятно, нет. Поэтому я думаю, что переключатели в ООП являются запахами кода, и оператор

, Включающий тип, является плохим стилем ООП, включение значения прекрасно.

самостоятельно упрощен.

И вернуться к начальному вопросу: switch не плохо, это - просто не всегда очень OO. Вы не должны использовать OO для решения проблемы. Если Вы действительно используете ООП, то переключатели - что-то, что необходимо уделить дополнительному вниманию.

16
ответ дан eljenso 15 October 2019 в 06:47
поделиться
Другие вопросы по тегам:

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