2013-07-21 20 views
8

Pracuję w języku C#, więc opublikowałem to pod C#, chociaż może to być pytanie, na które można odpowiedzieć w dowolnym języku programowania.Metody, które zwracają znaczące wartości zwracane

Czasami stworzę metodę, która zrobi coś takiego, jak zalogowanie użytkownika na stronie internetowej. Często zwracam wartość boolean z metody, ale często powoduje to problemy, ponieważ wartość zwracana przez boolowską wartość nie przekazuje żadnego kontekstu. Jeśli wystąpi błąd podczas logowania użytkownika, nie mam możliwości dowiedzenia się, co spowodowało błąd.

Oto przykład sposobu, że aktualnie w użyciu, ale chciałby zmienić tak, że zwraca więcej niż tylko 0 lub 1.

public bool LoginToTwitter(String username, String password) 
{ 
    // Some code to log the user in 
} 

powyższa metoda może zwracać tylko Prawda czy fałsz. Działa to dobrze, bo mogę po prostu zadzwonić następujący:.

if(http.LoginToTwitter(username, password)) 
{ 
    // Logged in 
} else { 
    // Not Logged in 
} 

Ale problem jest, nie mam pojęcia, dlaczego użytkownik nie był zalogowany w wielu powodów może istnieć takie jak: niewłaściwej nazwy użytkownika/hasła połączenie, konto zawieszone, konto wymaga uwagi użytkowników itp. Jednak przy użyciu poniższej metody i logiki nie można o tym wiedzieć.

Jakie mam alternatywne podejścia?

Odpowiedz

8

Można utworzyć i zwrócić wartość enum z oczekiwanymi wartościami LoginResults.

public enum LoginResult 
{ 
    Success, 
    AccountSuspended, 
    WrongUsername, 
    WrongPassword, 
} 

Następnie powrót przy użyciu typu enum w swojej metodzie:

public LoginResult LoginToTwitter(String username, String password) 
{ 
    // Some code to log the user in 
} 
+0

Co się stało, gdy wystąpił nowy warunek błędu. @Dan? – xhamr

+0

@jvra Jeśli są jakieś nieoczekiwane wyjątki, uważam, że powinny zostać ponownie zgłoszone, jak wskazują niektóre inne odpowiedzi. Jednak Twój kod powinien być w stanie obsłużyć wszystkie spodziewane przypadki: Złą nazwę użytkownika, nieprawidłowe hasło, zawieszenie konta, itp ... i zwrócić te oczekiwane przypadki w wyliczeniu, aby aplikacja mogła obsłużyć. –

+0

Ale faktem jest, kiedy chcesz obsłużyć inne wyliczenie błędów. Twój kod może się rozwinąć, gdy wyrośnie twoje stałe. ale jest do przyjęcia, jeśli wiesz, że w przyszłości nie można było wyliczyć więcej stałych. – xhamr

8

Można wybrać, czy wyjątek z odpowiednim komunikatem załączonym (i mają wiele metoda dzwonienie z wyjątkiem), lub funkcja zwraca wartość enum z różnymi stanami (takimi jak LoginState.Success, LoginState.IncorrectPassword itd.).

Jeśli używasz wyjątków, to chyba najlepiej mieć nic wspólnego powrotu funkcji (public void LoginToTwitter), ale jeśli używasz enum, upewnij się, że zestaw rodzaju powrót do nazwy swojej enum (public LoginState LoginToTwitter).

6

Istnieją dwa standardowe sposoby. Jeśli interesuje Cię tylko wynik, ale nie metadane, zwróć trochę wyliczenia. Ustaw dostępne wartości na Success, Suspended, itd. (Wszystkie możliwe wyniki)

Jeśli potrzebujesz więcej informacji, możesz zawsze użyć wyjątków. Zasadniczo postępuj zgodnie z ideą "powiedz, nie pytaj" i napisz swoją funkcję w taki sposób, aby zwracała wymagane wartości (np. Identyfikator użytkownika, a może nic, jeśli masz globalny stan logowania) tylko w przypadku sukcesu i zgłasza wyjątek ze szczegółowymi w przeciwnym razie opis błędu. Jeśli chodzi o samą hierarchię, powinieneś najprawdopodobniej zaimplementować LoginException z bardziej specyficznymi podklasami i przechwycić tylko te. (ułatwia weryfikację wszystkich istotnych wyjątków, a wszystkie nieznane są przekazywane na wyższe poziomy)

0

Zgodnie z czystą tendencją kodu należy podać znaczącą nazwę metody, która ujawni zamiar.

Aby dowiedzieć się, co się stanie, jeśli nie można ukończyć operacji logowania, można wprowadzić w swoim strumieniu Exceptions i postępować zgodnie z kontekstem wywołującego.

zobaczyć http://msdn.microsoft.com/en-us/library/ms173160(v=vs.80).aspx

3

Zarówno powrocie enum lub rzuca wyjątek, jak sugerowano w innych odpowiedzi, są uzasadnione. Ale moje preferencje są następujące: zwraca wyjątek. Brzmi szalenie, ale pozwala rozmówcy zdecydować, czy użyć sprawdzania błędów, czy obsługi wyjątków. W odróżnieniu od wyliczenia wyjątki są hierarchiczne, więc znacznie łatwiej radzą sobie z całymi kategoriami awarii i mogą przenosić dowolne dodatkowe dane.

Myślę, że Sayse miał podobny pomysł, ale skasował swoją odpowiedź i nigdy tak naprawdę nie wyjaśnił tego.

+0

Tak więc, 'null' oznaczałoby * sukces * - co wydaje się raczej sprzeczne z intuicją. I oczywiście, jeśli rzeczywiście potrzebujesz wartości zwracanej, takiej jak (powiedzmy) informacji o użytkowniku ... Widzę dobry przypadek w języku takim jak Smalltalk, który jest wpisywany dynamicznie, ale statycznie napisany język jak C# sprawia, że ​​jest to uciążliwe . – cHao

+0

@ cHao: Jeśli dalsze przetwarzanie wymaga zwrócenia kilku innych informacji, wówczas wyrzucanie wyjątków zaczyna nabierać większego sensu. Ale jeśli niepowodzenie logowania jest oczekiwanym rezultatem ... cóż, nie używam 'throw' w nietypowych warunkach. –

+0

Jestem w połowie zaskoczony, że nikt nie jest uważany za typ "LoginResult", który nie jest wyjątkiem, ale także nie jest tylko wyliczeniem. Zapewniłoby to elastyczność zwracania arbitralnych informacji, bez skłaniania ludzi do rzucania wyjątków w nietypowych warunkach. – cHao

0

Możesz użyć idiomu, który jest często używany w c. Wynikiem wyrażenia przypisania jest sam wyraz - to oznacza, że ​​można uchwycić kod wynikowy w tym samym czasie, oceny czy jest to szczególna wartość:

if ((status = DoSomething()) == AnErrorEnum.NotAnError) 
{//success handler 
} 
else 
{//failure handler 
} 

zostałem poproszony o podanie linka do artykułu MSDN - tutaj jest starsza wersja specyfikacji: http://msdn.microsoft.com/en-us/library/aa691315(v=vs.71).aspx

"Wynik prostego wyrażenia przypisania jest wartością przypisaną do lewego argumentu operacji.Opcja ma ten sam typ co lewy operand i zawsze jest klasyfikowana jako wartość. "

+0

To jest interesujące. Czy jest jakiś link do dokumentów MSDN? –

+0

Jest w specyfikacji, która jest dostępna do pobrania: Oto sekcja starej specyfikacji z 2003 roku: http://msdn.microsoft.com/en-us/library/aa691315(v=vs.71).aspx –

Powiązane problemy