Замена вложенных операторов if - PullRequest
28 голосов
/ 03 декабря 2008

Это относится к главе из красивого кода . И в этой главе я читал о вложенных if s.

Автор говорил о глубоко вложенных if с как источник ошибок и менее читабельный. И он говорил о замене вложенных if s на case операторов и таблиц решений .

Кто-нибудь может проиллюстрировать, как удалить вложенные if с case (select case) и таблицы решений?

Ответы [ 11 ]

21 голосов
/ 03 декабря 2008

Ну, это не прямой ответ на ваш вопрос, так как вы специально спрашиваете о выражениях переключения / случая, но вот похожий вопрос.

Инвертировать оператор «if» для уменьшения вложенности

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

10 голосов
/ 03 декабря 2008

Один пример, который я всегда пытаюсь сделать, это заменить сильно вложенные if, если это так (на самом деле это не слишком плохо, но я видел их на глубине до 8 или 9 уровней в дикой природе):

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

с этим:

switch (i) {
    case 1:
        // action 1
        break;
    case 2:
        // action 2
        break;
    case 3:
        // action 3
        break;
    default:
        // action 4
        break;
}

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

Таблицы решений, я полагаю, просто устанавливают флаги, указывающие, какие действия необходимо предпринять позже. Раздел «позже» представляет собой простую последовательность действий на основе этих флагов. Я могу ошибаться (это будет не первый или последний раз: -).

Примером может быть (фаза установки флага может быть сложной, если она такова, поскольку ее действия очень просты):

switch (i) {
    case 1:
        outmsg = "no paper";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    case 2:
        outmsg = "no ink";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    default:
        outmsg = "unknown problem";
        genmsg = true;
        mailmsg = true;
        phonemsg = true;
        break;
}

if (genmsg)
    // Send message to screen.
if (mailmsg)
    // Send message to operators email address.
if (phonemsg)
    // Hassle operators mobile phone.
9 голосов
/ 03 декабря 2008

Как насчет цепей, если?

Заменить

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

с

if (condition1) {
   do1;
} else if (condition2) {
   do2;
} else if (condition3) {
   do3;
}

Это очень похоже на оператор switch для сложных условий.

6 голосов
/ 03 декабря 2008

Превратите условие в логическое значение, а затем напишите логическое выражение для каждого случая.

Если код был:

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

Можно записать как:

bool cond1=condition1;
bool cond2=condition2;
bool cond3=condition3;

if (cond1) {do1;}
if (!cond1 and cond2) {do2;}
if (!cond1 and cond3) {do2;}
3 голосов
/ 03 декабря 2008

Таблицы решений см. В моем ответе на этот вопрос , или, что еще лучше, прочитайте главу 18 в Code Complete 2 .

2 голосов
/ 16 мая 2015

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

function validate(){
  if(b=="" || b==null){
      alert("Please enter your city");
      return false;
  }

  if(a=="" || a==null){
      alert("Please enter your address");
      return false;
  }
  return true;
}
1 голос
/ 03 декабря 2008

Таблицы решений - это где хранит условную логику в структуре данных, а не в самом коде .

Итак, вместо этого (используя пример @ Pax):

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

вы делаете что-то вроде этого:

void action1()
{
    // action 1
}

void action2()
{
    // action 2
}

void action3()
{
    // action 3
}

void action4()
{
    // action 4
}

#define NUM_ACTIONS 4

// Create array of function pointers for each allowed value of i
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 }

// And now in the body of a function somewhere...
if ((i < NUM_ACTIONS) && actions[i])
    actions[i]();
else
    action4();

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

Этот метод становится намного более полезным, чем вложенные операторы if s или switch, когда вы принимаете решение по десяткам возможных значений.

0 голосов
/ 03 октября 2013

Вложено, если эквивалентно логическому оператору И

if (condition1)
{
    if (function(2))
    {
        if (condition3)
        {
            // do something
        }
    }
}

Эквивалентный код:

if (condition1 && function(2) && condition3)
{
    // do something
}

В обоих случаях, когда выражение оценивает false, последующее выражение не будет оцениваться. Например, если условие 1 ложно, функция () не будет вызываться, а условие 3 не будет оцениваться.

0 голосов
/ 03 декабря 2008

Вы также можете использовать Шаблон посетителя .

0 голосов
/ 03 декабря 2008

Операторы If и switch не являются чисто OO. Они являются условной процедурной логикой, но делают очень хорошую работу! Если вы хотите удалить эти операторы для более OO-подхода, объедините шаблоны 'State' и 'Descriptor' .

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