Обработка более 2 возможных возвращаемых значений? - PullRequest
2 голосов
/ 31 августа 2009

Когда функция возвращает логическое значение, вы можете легко

if (task()){
   // it worked!
}else{
   // it failed.
}

Но когда он возвращает несколько разных значений, он становится более беспорядочным

var status = task();
if (status == 1){
   // hmm
}else if (status == 2){
   // hmmmmm
}else if (status == 3){
   // hmmmmmmmm!
}

.. есть ли более аккуратный способ справиться с этим?

Редактировать: В ответ на ответы, которые рекомендуют заявления переключателя, да, я знаю о них. Я просил что-то более аккуратное, чем даже это?

Ответы [ 6 ]

5 голосов
/ 31 августа 2009

Я не могу сказать, какой язык вы используете (JavaScript?), Но я обычно пишу такой код:

var result = task();

switch (result)
{
    case 1:
        handleStatus1();
        break;
    case 2:
        handleStatus2();
        break;
    default:
        handleEverythingElse();
        break;
}
2 голосов
/ 31 августа 2009

Зависит от возможностей языка, но я бы сделал что-то подобное в JavaScript:

var handle_task_1 = function () {
    // handle task 1
};

var handle_task_2 = function () {
    // handle task 2
};

var tasks = {
    1: handle_task_1,
    2: handle_task_2,

    "default": function() {},
};

tasks[task()]();

// Or, with a default action. But it may be too much for some people :)
(tasks[task()] || tasks["default"])();
1 голос
/ 31 августа 2009

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

Код будет выглядеть так

Action action = (Action) contextMap.get(task());
action.do();

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

В этом подходе есть и другие приятные вещи

  1. taskA () и taskB () могут совместно использовать одну и ту же contextMap и даже некоторые из одних и тех же действий, поэтому у вас меньше дублирования кода
  2. Действия могут быть проверены юнитом легче (обычно)
  3. Совместное использование кода между действиями будет простым без использования спагетти-кода или сложных операторов if (status> 2 && status! = 7)

И, конечно, здесь помогают интерфейсы, varargs и другие синтаксические сахара.

1 голос
/ 31 августа 2009

Большинство языков имеют оператор switch , что-то вроде:

switch (task()) {
   case 1: // do stuff
      break;
   case 2: // other stuff
      break;
   /// etc.
   default: // what?!
      Error("Unhandleable status code");
}
0 голосов
/ 31 августа 2009

Может быть, вы ищете исключения ?

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

0 голосов
/ 31 августа 2009

Если вы говорите о целочисленном или другом примитивном типе возврата, лучший из известных мне подходов - оператор switch.

switch (status)
{
case 1:
  // hmm
  break;
case 2:
  // hmmm
  break;
}

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

Допустим, у вас есть интерфейс ISomething и два (или более) объекта, которые реализуют этот интерфейс (ASomething и BSomething). Если тип возврата метода ISomething, код становится:

ISomething result = task();
result.DoSomething();
...