PHP - вложенные выражения IF

Мне интересно , когда это плохая идея использовать несколько вложенных операторов IF.

например:

function change_password($email, $password, $new_password, $confirm_new_password)
{
    if($email && $password && $new_password && $confirm_new_password)
    {
        if($new_password == $confirm_new_password)
        {
            if(login($email, $password))
            {
                if(set_password($email, $new_password))
                {
                    return TRUE;
                }
            }
        }
    }
}       

Эта функция используется следующим образом:

if(!change_password($email, $password, $new_password, $confirm_new_password)
{
    echo 'The form was not filled in correctly!';
    exit;
}

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

Я не вижу много других сценариев, написанных следующим образом: вложенный IF формирует треугольную форму и только имеет желаемый результат в самой середине. Если середина не достигнута, то что-то прищурилось.

Является ли это хорошей функциональной структурой?

Ответ 1

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

function change_password(blah blah blah) {
   if (!$condition1) {
      return false;
   }
   if (!$condition2) {
      return false;
   }
   etc....


   // got here, must have succeeded
   return true;
}

Это явно указывает, что такое логическая последовательность.

Ответ 2

Я думаю, что он определенно хорошо читаем и его легко понять по сравнению с использованием только одного if оператора, такого как

if (blah and blah and blah and blah and blah and blah and blah) {}

Однако я бы предпочел сделать это так - слишком много отступов может вызвать раздражение:

function change_password($email, $password, $new_password, $confirm_new_password)
{
    if (!$email || !$password || !$new_password || !$confirm_new_password) return false;
    if ($new_password != $confirm_new_password) return false;
    if (!login($email, $password)) return false;
    if (!set_password($email, $new_password)) return false;

    return true;
}

Ответ 3

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

function change_password($email, $password, $new_password, $confirm_new_password)
{
    if($new_password == $confirm_new_password && $email && $password && $new_password && $confirm_new_password)
    {
        if(login($email, $password))
        {
            if(set_password($email, $new_password))
            {
                return TRUE;
            }
        }

    }
}

Если $new_password == $confirm_new_password истинно, но $email пуст, вы сделаете дополнительное сравнение.

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