Как избежать если ... еще и переключать дела - PullRequest
9 голосов
/ 03 августа 2010

Я программировал много времени. Обычно я программирую на некоторых языках, таких как PHP, ASP.net, Java, JavaScript и другие. На всех языках я должен использовать множество инструкций if else. Например, если значение = 10, то ... если я рассмотрю свой код, то я найду много условий if. Поэтому я хотел бы свести их к минимуму, но не уверен.

В одном пункте использовались несколько минимизированные классы, но все же они более ...

как задание, кошка, сек и тип:

if task = 'add' then
   if cat = "animal" then
      if sec = "man" then
          if type = "male" then
                 'do the following stuffs
          else
                 'do the following stuffs
          end if
      elseif sec = "horse" then
          if type = "run"
                 'do the following stuffs
          else
                 'do the following stuffs
          end if
      elseif....
      end if
   elseif cat = "plant" then
     if sec = "land" then
          if type="tree" then
                 'do the following stuffs
          elseif type = "grass" then..
                 'do the following stuffs
          elseif...
          end if
    elseif sec = "water" then
    ...
...

...

больше и больше продолжить и продолжить

так интересно, как я могу минимизировать их и написать несколько эффективных кодов?

Извините, что недавно сообщил, что может быть много значений для задачи, кошки, секунды и типа. Мои операторы if будут вложенными. N 1014 *

Более подробно, мой код также выглядит так же, как:

http://thedailywtf.com/Articles/Coding-Like-the-Tour-de-France.aspx

Ответы [ 9 ]

14 голосов
/ 03 августа 2010

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

4 голосов
/ 03 августа 2010

Предполагая, что вы всегда проводите сравнение на равенство и сравниваете все четыре поля, простой подход, основанный на данных, весьма практичен.Все, что вам нужно сделать, это построить карту из (task, cat, sec, type) в функцию для вызова:

handlers = {
    ('add', 'animal', 'man', 'male'): add_man_func,
    ('add', 'animal', 'horse', 'run'): run_horse_func,
    # ...
}

handler = handlers[(task, cat, sec, type)]
handler(some_args)
4 голосов
/ 03 августа 2010

Это называется «Стрелка Антипаттерн» Некоторые методы борьбы с ним описаны здесь: http://c2.com/cgi/wiki?ArrowAntiPattern

Один из способов, который вы рассматриваете, - это рефакторинг кода на вложенных уровнях для разделения функций, таких как

if cat = "animal" then
  functionForAnimal();
elseif cat = "plant" then
 functionForPlant();
elseif...


function functionForAnimal() 
  if sec = "man" then
    functionForMan();
  elseif sec = "horse" then
    functionForHorse();
  elseif...

etc...

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

2 голосов
/ 03 августа 2010

Вы описали матрицу с 4 входящими параметрами - task, cat, sec, type и одним исходящим - stuff.Поэтому вам нужно как-то кодировать его.

Например, карта XML и запрос XPath, т.е. String.Format("task[@value={0}]/cat[@value={1}]/sec[@value={2}]/type[@value={3}]", "add", "animal", "man", "male"), но этот подход указывает на данные, а не на делегат метода.

Другой способ

void DoStuffA() { }
void DoStuffB() { }

var arr = new[]
{
    new { Task = "Add", Cat = "Animal", Sec = "Man", Type = "Male", Method = (Action)DoStuffA },
    new { Task = "Add", Cat = "Plant", Sec = "Land", Type = "Tree", Method = (Action)DoStuffB },
    // etc..
};

var action = arr.FirstOrDefault(i =>
     i.Task == "Add" &&
     i.Cat == "Animal" &&
     i.Type == "Male").Method;
action();

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

2 голосов
/ 03 августа 2010

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

1 голос
/ 03 августа 2010

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

В любом случае, если вы действительно используете Java (или что-то с классами), вам нужна абстракция.Затем перенесите всю логику на свои объекты - не обрабатывайте ее в одной чудовищной рутине.Подумайте так: мои объекты знают, как выполнять свою роль.

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

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

0 голосов
/ 03 августа 2010

Разбиение кода - вот и все, о чем игра.

Исторически вы бы поступили (и был хороший, или, по крайней мере, стабильный код, и все же есть во всех них)

  • как вы делаете это сейчас, монолитный в огромных функциях, с большим количеством комментариев

  • разделите его на маленькие четко определенные и хорошо именованные функции

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

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

0 голосов
/ 03 августа 2010

Где-то вам нужно будет проверить условия с помощью if-elses, чтобы убедиться, что вы поступаете правильно.Вы можете создавать новые сабвуферы, если не хотите втиснуть один саб

Sub AddAnimalManMale()
    If task = 'add' And cat = 'animal' And sec = 'man' And type = 'male' Then
        'perform the add animal man male action'
    End If
End Sub
Sub AddAnimalHorseRun()
    If task = 'add' And cat = 'animal' And sec = 'horse' And type = 'run' Then
        'perform the add animal horse run action'
    End If
End Sub

, а затем в свой основной саб

...
Call AddAnimalManMale()
Call AddAnimalHorseRun()
...
0 голосов
/ 03 августа 2010

Если выбор для каждой из этих переменных конечен, то вы даже можете использовать трюки, такие как битовые поля, с операцией ИЛИ.

Пример:

// give each field a byte so that each can have 256 possible values
#define TASK_ADD 0x01
#define TASK_SUB 0x02
...
#define CAT_ANIMAL 0x01
...
#define SEC_BOY 0x03
#define SEC_MAN 0x04
...
#define TYPE_FEMALE 0x01
#define TYPE_MALE 0x02
...

if ((task << 24 | cat << 16 | sec << 8 | type) == 0x01010402) {
  // do stuff
}
...