2010-10-23 12 views
6

To pytanie: Best way to return status flag and message from a method in Java jest podobne do mojego, jednak zrobiłbym to w PHP, a nie w Javie (co może zrobić tutaj niewielką różnicę).Powrót do stanu metody: bool, string, const ... (PHP)

Problem:

Jest to metoda, która może mieć zarówno pozytywne wyniki (może się to zmienić, aby być bardziej udanych) lub „problematyczna” jeden. To ostatnie oznacza, że ​​operacja się nie udała, ale ważne jest również, aby wiedzieć, dlaczego. Wyobraźmy sobie metodę klasy Uwierzytelnianie:

public function login($name, $password) 
{ 
    if (successful_authentication) 
    { 
     report success 
    } 
    else 
    { 
     report failure, explain why (e.g. wrong name/pass, user banned) 
    } 
} 

byłoby trywialne, aby powrócić true i false dla sukcesu i porażki, ale jak zgłaszać przyczynę niepowodzenia?

Możliwe rozwiązania:

  • return true lub false i napiszę inną metodę (getStatus()), aby uzyskać konkretny problem: to czuje się trochę dziwne dla mnie
  • Wpisz wyjątki: ponieważ nie jest wyjątek dla użytkownika, który ma być zbanowany (wyjątkiem byłby, gdyby użytkownik umarł podczas pisania, jak wskazał inny autor na tej stronie) użycie wyjątków w tych przypadkach byłoby błędne (jednak metoda mogłaby rzucić wyjątek bazy danych jeśli zapytanie nie powiedzie się)
  • return true w przypadku powodzenia i ciąg na niepowodzenie z kodem błędu wskazujący problem: PHP jest to możliwe w ten sposób, aby mieć ładne, czyste bloki, co następuje:

    $loginStatus = $auth->login('name', 'pass'); 
    if ($loginStatus === true) 
    { 
        doSomething(); 
    } 
    else 
    { 
        if ($loginStatus == 'wrong_login_data') 
        ... 
        elseif ($loginStatus == 'banned') 
        ... 
        // or with an array full of error messages: 
        echo $erroMessages[$loginStatus]; 
    } 
    
  • Return ogólny stan (stan) obiektu: bardzo eleganckie rozwiązanie, a także przyszłościowy (nie ma problemu, jeśli liczba stanów waha czy później dodatkowe dane powinny być zwrócone), być może najlepszy:

    $loginStatus = $auth->login('name', 'pass') 
    if ($loginStatus->isSuccess) 
    ... 
    else 
        echo $errorMessages[$loginStatus->errorCode]; // $errorMessages as by the previous example 
    
  • Każda z dwóch poprzednich, ale nie ze zwykłego sznurka ale stałe klas:

    $loginStatus = $auth->login('name', 'pass') 
    if ($loginStatus->isSuccess) 
    ... 
    elseif ($loginStatus->errorCode == Auth::ERR_USER_BANNED) 
    ... 
    

    Dzięki temu nie byłoby konieczne objaśnianie kodów błędów w dokumentacji i czułbym się bardziej "naturalny" (przynajmniej dla mnie).

Pytanie:

Co należałoby użyć (z powyższych te lub jakiekolwiek inne rozwiązanie)? Co zostało udowodnione na dłuższą metę, aby być dobrym sposobem?

Z góry dziękuję!

Odpowiedz

2

W ten sposób PEAR robił to tak długo, jak długo pamiętam. Jest to wypróbowana i przetestowana metoda.

class LoginError { 
    private $reason; 

    public function __construct($reason) 
    { 
     $this->reason = $reason; 
    } 

    public function getReason() 
    { 
     return $this->reason; 
    } 
} 

function isError($response) 
{ 
    return ($response instanceof LoginError); 
} 

public function login($name, $password) 
{ 
    if (successful_authentication) 
    { 
     return true; 
    } 
    else 
    { 
     return new LoginError('The password is incorrect'); 
    } 
} 


$loginStatus = login('name', 'pass'); 
if (!isError($loginStatus)) 
{ 
    doSomething(); 
} 
else 
{ 
    echo $loginStatus->getReason(); 
} 
+0

Szkoda, że ​​tak długo czekałem z akceptacją odpowiedzi :-). – Piedone

2

Zgłaszanie wyjątków. Jeśli sprawdzanie wartości zwracanej jest wymagane, wówczas każde niepowodzenie spowoduje nieautoryzowane logowanie. Niewykonanie sprawdzania wyjątku spowoduje dmuchnięcie w całość, co wydaje się lepsze w tym przypadku.

W mniej krytycznych miejscach, gdy sprawdzałem obiekt, który już istniał, mogę po prostu zwrócić kod wyniku i mieć oddzielną funkcję do pobrania wiadomości, ale nie robiłbym nic, aby coś zrobić. do obiektu, aby użyć tej techniki. W przeciwnym razie przejdę do obiektu statusu zawierającego kod wyniku i wiadomość.

+0

Dzięki za odpowiedź! Zauważ, że byłaby to tylko metoda logowania, ale nie metoda sprawdzania, czy użytkownik jest już uwierzytelniony (nie robić tego, by rzeczywiście powodować problemy). Nie sądzę, aby niepowodzenie w logowaniu było wyjątkiem (pomyśl tylko o błędnym wpisaniu hasła - nie jest to bardzo rzadki przypadek), a zatem byłoby to użycie wyjątków dla normalnego przepływu programu. Ale nie myślmy tylko o metodzie logowania, chciałbym wiedzieć, jaka jest najlepsza technika z jakąkolwiek metodą, która może mieć udane i nieudane stany. – Piedone

+0

@piedone - edytowany –

1

Wybrałbym wariant "Zwróć obiekt stanu ogólnego (stanu)", gdzie stan jest opisany przez twój obiekt auth.

Więc $ auth-> login ('name', 'pass') jest prostym boolem, a $ auth-> getState() to enum lub ciąg znaków (przeznaczone dla użytkownika końcowego) opisujące stan.

Powiązane problemy