I'm wondering when it's a bad idea to use multiple nested IF statements.
eg:
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;
}
}
}
}
}
This function is used like this:
if(!change_password($email, $password, $new_password, $confirm_new_password)
{
echo 'The form was not filled in correctly!';
exit;
}
I call all my functions like this, and I'm wondering if there's something wrong with my coding style. I'm having my doubts because if I follow this design then that means every single function I write will just be with nested with IF's, checking if there are errors at every stage. Is this what other people do?
I don't see many other scripts written like this, with the nested IF's making a triangle shape and only having the desired result in the very middle. If the middle isn't reached, then something screwed up.
Is this a good function structure?
Nesting too deeply is generally a bad idea - it's spaghetti logic and difficult to follow. Since each of your verification steps depends on the previous stage having succeeded, don't nest at all - just bail out when a stage fails:
function change_password(blah blah blah) {
if (!$condition1) {
return false;
}
if (!$condition2) {
return false;
}
etc....
// got here, must have succeeded
return true;
}
That makes it explicitly clear what the logic sequence is.
I think it is definitely well readable and can easily be understood in comparison to using just one if
statement like
if (blah and blah and blah and blah and blah and blah and blah) {}
However I'd still prefer doing it this way - too much indention can get kinda annoying:
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;
}
It can be good to nest them, because by changing the order you may be able to avoid making extra comparisons. What you are doing now looks good, however your function would be less efficient if you instead wrote it as:
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;
}
}
}
}
If $new_password == $confirm_new_password is true, but $email is empty, you will have made an extra comparison.
As others have said, there are other ways to go about this without nesting everything, which will be functionally equivalent.