Подтвердить что ты не робот

Заявления операторов плохие?

Недавно я узнал, что операторы switch плохо работают в ООП, особенно из "чистого кода" (p37-39) Роберта Мартина.

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

4b9b3361

Ответ 1

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

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

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

Но это настоящая боль.

Оцените, есть ли такой вариант дизайна, как перечисление, которое возможно в вашем решении. Если нет, просто используйте переключатель.

Ответ 2

Операторы switch

'Bad' часто включают в себя тип объекта (или что-то, что может быть типом объекта в другом проекте). Другими словами, жестко кодировать то, что может быть лучше обработано полиморфизмом. Другие типы операторов switch могут быть в порядке

Вам понадобится оператор switch, но только один. Когда вы получите сообщение, вызовите объект Factory, чтобы вернуть объект соответствующего подкласса Message (Move, Attack и т.д.), Затем вызовите метод message- > doit() для выполнения работы.

Это означает, что если вы добавляете больше типов сообщений, нужно изменить только объект Factory.

Ответ 3

Приходит в голову шаблон Strategy.

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

В этом случае "семейство алгоритмов" - это ваши разные действия.


Что касается операторов switch - в "Чистом коде", Роберт Мартин говорит, что он пытается ограничиться одним оператором switch для каждого типа. Не устраняйте их вообще.

Причина в том, что операторы switch не придерживаются OCP.

Ответ 4

С точки зрения дизайна вы можете использовать Command Pattern для данного сценария. (См. http://en.wikipedia.org/wiki/Command_pattern).

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

Для получения дополнительной информации о том, как вы удаляете эти операторы switch и вводите соответствующие подклассы, я рекомендую вам прочитать первую главу "Рефакторинг" Мартина Фаулера. Или вы можете найти похожие слайды здесь http://www1.informatik.uni-wuerzburg.de/database/courses/pi2_ss03_dir/RefactoringExampleSlides.pdf. (Слайд 44)

Ответ 5

Я бы поместил сообщения в массив и затем сопоставил элемент с ключом решения, чтобы отобразить сообщение.

Ответ 6

Заявления IMO switch не плохие, но их следует избегать, если это возможно. Одним из решений было бы использовать Map, где ключи - это команды, а значения Command - объекты с методом execute(). Или List, если ваши команды являются числовыми и не имеют пробелов.

Однако, как правило, вы должны использовать инструкции switch при реализации шаблонов проектирования; одним примером может быть использование шаблона Chain of charge для обработки команд, заданных любой командой "id" или "value". (Также был отмечен шаблон Strategy.) Однако в вашем случае вы также можете посмотреть Command шаблон.

В основном, в ООП вы попытаетесь использовать другие решения, чем полагаться на блоки switch, которые используют парадигму процедурного программирования. Однако, когда и как использовать это - это ваше решение. Я лично часто использую блоки switch при использовании шаблона Factory и т.д.


Определение организации кода:

  • пакет - это группа классов с когерентным API (ex: Collection API во многих рамках)
  • класс представляет собой набор когерентных функциональных возможностей (например: a Math class...
  • метод - это функциональность; он должен делать только одно и только одно. (например: добавление элемента в список может потребовать, чтобы увеличить указанный список, и в этом случае метод add будет полагаться на другие методы, чтобы сделать это, и не будет выполнять эту операцию сам, потому что он не заключает контракт.)

Поэтому, если ваш оператор switch выполняет разные виды операций, вы "нарушаете" это определение; тогда как использование шаблона проектирования не выполняется, поскольку каждая операция определена в нем собственным классом (собственным набором функций).

Ответ 7

Используйте команды. Оберните действие в объект и пусть полиморфизм сделает для вас переключатель. В С++ (shared_ptr - это просто указатель или ссылка на языке Java, что позволяет динамически отправлять):

void GameServer::perform_action(shared_ptr<Action> op) {
    op->execute();
}

Клиенты выбирают действие для выполнения, и как только они это делают, они отправляют это действие самому серверу, поэтому серверу не нужно выполнять синтаксический анализ:

void BlueClient::play() {
    shared_ptr<Action> a;
    if( should_move() ) a = new Move(this, NORTHWEST);
    else if( should_attack() ) a = new Attack(this, EAST);
    else a = Wait(this);
    server.perform_action(a);
}

Ответ 8

Я не покупаю его. Кажется, что у этих фанатиков ООП есть машины, у которых есть бесконечная оперативная память и потрясающая производительность. Очевидно, что при использовании inifinite RAM вам не нужно беспокоиться о фрагментации ОЗУ и о влиянии производительности, которое возникает при непрерывном создании и уничтожении небольших вспомогательных классов. Перефразируя цитату из книги "Красивый код" - "Каждая проблема в информатике может быть решена с еще одним уровнем абстракции"

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