Кто-нибудь не согласен с утверждением: «использование switch - плохой стиль ООП»? - PullRequest
26 голосов
/ 15 февраля 2009

Я видел, как в нескольких потоках / комментариях к stackoverflow написано, что использование switch - просто плохой стиль ООП. Лично я с этим не согласен.

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

Наконец, переключатели лаконичны и понятны:

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

Я не защищаю каждое использование switch, и я не говорю, что всегда есть путь. Но такие утверждения, как «Переключатель - это запах кода», на мой взгляд, просто неверны. Кто-нибудь еще согласен?

Ответы [ 22 ]

2 голосов
/ 15 февраля 2009

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

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

2 голосов
/ 16 февраля 2009

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

Кроме того, ООП - это не серебряная пуля. Иногда это ответ, иногда нет.

2 голосов
/ 16 февраля 2009

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

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

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

2 голосов
/ 15 февраля 2009

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

2 голосов
/ 15 февраля 2009

Î знаю, откуда ты. Некоторые языки заставляют вас делать это.

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

И что теперь? Конечно, есть хороший способ ООП сделать это:

str.request(this);

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

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

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

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

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

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

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

А теперь найдите компромисс.

Грустно, я знаю.

1 голос
/ 16 февраля 2009

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

Итак, я переформулирую вопрос так: «Использует ли переключатель признак плохого кода?» , потому что это действительно то, что меня волнует. Теперь я перейду к ответу.

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

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

1 голос
/ 16 февраля 2009

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

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

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

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

1 голос
/ 15 февраля 2009

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

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

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

Такой подход упростит клиентский код. Код клиента не должен знать подробности того, как рассчитывается «инвестируемость», и ему больше не нужно нарушать закон Деметры , копаясь в состоянии объекта Customer.

1 голос
/ 15 февраля 2009

Да, мне надоели люди, говорящие, что это плохой стиль.

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

1 голос
/ 15 февраля 2009

И что теперь? Конечно, есть хороший ООП способ сделать это:

str.request (это);

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...