Jak poprawnie używać bloków logicznych if

|
Robert
| komentarze | Programowanie - Teoria

 

 

Instrukcja warunkowa if to element języków programowania który służy do warunkowania poszczególnych operacji w zależności od stanu programu. Wyróżniamy ogólnie dwa stany: TRUE oraz FALSE czyli kolejno prawda i fałsz. Nie będę się zagłębiać w szczegóły jeśli chodzi o Algebrę Boole'a i sposoby budowania takich instrukcji warunkowych za pomocą operatorów. Dziś spróbuję rzucić światło na temat instrukcji warunkowych z trochę innej strony.

Klasycznie w wielu poradnikach programowania oraz różnego rodzaju rozwiązaniach ze StackOverflow możemy znaleźć takie propozycje rozwiązania problemów:

const jakasFunkcja = () => {
  if (warunek1) {
    instukcja1();
    if (warunek2) {
      if (warunek3) {
        instrukcja3();
      }
    }
    else {
      instrukcja2();
    }
  }
}

Powyższy przykład technicznie jest poprawny, ale zwróć uwagę na problem, że jeśli kod zostanie jeszcze bardziej rozbudowany, to będzie trudniejszy w dalszej rozbudowie. Rozważmy proces logowania użytkownika na dwóch skrajnych przykładach przy częściowym pominięciu Right Ways programowania.

function loginUser ( $user, $password ) {

    if ( !isLogged() ) {
      //sprawdzamy, czy użytkownik jest już zalogowany

      if ( !empty($user) && !empty($password) ) {
        //sprawdzamy, czy zmienne wejściowe nie są puste
        
        $userData = getUser( $user );
        
        if ( $userData !== null ) {
          //sprawdzamy czy użytkownik istnieje
          
          if ( password_verify( $password, $userData[ '' ] ) )
          {
            //sprawdzamy czy hasło się zgadza
            $sessResult = createSession( $user );

            if ( $sessResult ) {
              //jak sesja została stworzona poprawnie to zalogowany.
              
              notifyAndRedir( '/','Zalogowano poprawnie' );
              
            }
            else {
              notifyAndRedir( URL_BACK,'Wystąpił błąd podczas logowania' );
            }
            
          }
          else {
            notifyAndRedir( URL_BACK,'Użytkownik nie istnieje lub hasło nie jest poprawne' );
          }
          
        }
        else {
          notifyAndRedir( URL_BACK,'Użytkownik nie istnieje lub hasło nie jest poprawne' );
        }
        
      }
      else {
        notifyAndRedir( URL_BACK,'Jedno z pól nie zostało wypełnione' );
      }
      
    }

    redirect('/');

Celowo pominąłem operacje podnoszące bezpieczeństwo aplikacji takie jak sprawdzanie zawartości zmiennych wejściowych. Mimo usilnych starań kod nie jest zbytnio czytelny i niewygodny do dalszych modyfikacji. Spójrzmy teraz na tą samą logikę z nieco innej perspektywy.

 

  //funkcja logująca użytkownika na podstawie loginu oraz hasła
  function loginUser ( $user, $password ) {

    if ( isLogged() ) {
      //sprawdzamy, czy użytkownik jest już zalogowany
      redirect('/');
    }

    
    if ( empty($user) || empty($password) ) {
      //sprawdzamy, czy zmienne wejściowe nie są puste

      notifyAndRedir( URL_BACK,'Jedno z pól nie zostało wypełnione' );

    }

    $userData = getUser( $user );
        
    if ( $userData === null || !password_verify( $password, $userData[ '' ] ) ) {
        /* sprawdzamy czy użytkownik istnieje oraz czy hasło się zgadza
          Wykorzystując kolejność sprawdzania warunków i wiedzę, że jeśli
          $userData !== null to przejdzie do sprawdzenia password_verify
        */

        notifyAndRedir( URL_BACK,'Użytkownik nie istnieje lub hasło nie jest poprawne' );

    }
      
    $sessResult = createSession( $user );

    if ( !$sessResult ) {
      //jak sesja została stworzona poprawnie to zalogowany.

      notifyAndRedir( URL_BACK,'Wystąpił błąd podczas logowania' );
      
    }
              
    notifyAndRedir( '/','Zalogowano poprawnie' );
    
  }

 

 

Powyższy kod jest zdecydowanie czytelniejszy i łatwiejszy do modyfikacji, ponadto jest krótszy. Warto zastanowić się nad tym, w jakim sposób budować instrukcje. Przy okazji wskazówka, warto podczas sprawdzania czy użytkownik istnieje oraz przy porównywaniu hasła pokazywać ten sam komunikat ("Użytkownik nie istnieje lub hasło nie zgadza się") ponieważ uodparnia to aplikację pod względem bezpieczeństwa, atakujący nie ma pewności czy zgadł już użytkownika, czy też nie i może przystąpić do odgadywania hasła.