Wyrzucanie wyjątków w metodach

Odpowiedz Nowy wątek
2020-07-04 06:29

Rejestracja: 5 miesięcy temu

Ostatnio: 7 godzin temu

0

Co sądzicie o takiego typu podejściu

public void SomeMethod(SomeClass obj)
    {
        if(obj==null)
            throw new Exception("Message");
        if(obj.prop==true)
            throw new Exception("AnotherMessage");
        //some logic
    }

Czyli wyrzucaniu wyjątków w metodzie. Słyszałem, że nie powinno się ich wyrzucać, gdyż to zmusza programistę, który przejmie kod, do pamiętania o tym aby je obsłużyć. Dla mnie trochę ten argument nie ma sensu, dlatego pytam się was. Dodam że ify sprawdzają poprawność danych (otrzymanych od serwera jsona) i w przypadku gdy są niepoprawne (wchodzą w te instrukcje warunkowe) aplikacja nic nie może zrobić (ich niepoprawność jest krytyczna).
Co o tym sądzicie? Powinienem tak rzucać wyjątkami w metodzie? Może jest inny powód dlaczego tak nie robić?

Pokaż pozostałe 2 komentarze
a to jest serwer który stoi obok i masz na niego wpływ czy jakieś zewnętrzny? - Miang 2020-07-04 10:07
Nie mam za bardzo na niego wpływu. To serwer zewnętrznej firmy. Pobieram tylko z niego dane. - Kordoba 2020-07-04 10:15
to niech metoda zwraca booleana w przypadku niemożliwości sparsowania . - Miang 2020-07-04 10:36
A czy twoje podejście ze zwrotem boola nie jest używane w przypadku, gdy wiesz, że są przypadki, że serwer zwróci dane, dla których aplikacja nic nie może zrobić i kończy działanie. Czyli to są dane których się spodziewasz (wiesz, że taki przypadek może wystąpić). A ja te wyjątki wyrzucam wtedy, gdy z mojego punktu widzenia, takie dane nie mogą być zwrócone z serwera (chyba że przez jakiś błąd po stronie serwera lub komunikacji z nim) - Kordoba 2020-07-04 10:52
błąd komunikacji to musisz obsłużyć i to jeszcze przed próbą parsowania , tylko że wtedy nie zmykasz aplikacji a dajesz możliwość ponownej próby komunikacji po określonym czasie. W tej metodzie rozumiem że sprawdzasz poprawność danych a nie trzymasz całą opartą na nich logikę aplikacji? - Miang 2020-07-04 11:16

Pozostało 580 znaków

2020-07-04 08:34

Rejestracja: 1 rok temu

Ostatnio: 9 godzin temu

0

A gdzie można jeszcze wyrzucać wyjątki jak nie w metodzie? Na pewno rzucenie wyjątkiem w sytuacji... wyjątkowej jest lepsze niż zwrócenie nulla czy zignorowanie i udawanie że nic się nie stało. Kod który korzysta z metody musi mieć możliwość rozróżnić sytuację wyjątkową od poprawnej wartości. Wszystko zależy od sytuacji ale najgorsze są biblioteki (a zdarzają się takie) które połykają wszystkie wyjątki w środku i nie mamy żadnej możliwości wykrycia i przekazania userowi z jakiego powodu program nie zadziałał. Nie mamy pańskiego płaszcza i co pan nam zrobi?

Ogólnie jeśli to normalny flow programu, a te "nieprawidłowe" dane są dość częste lub pochodzą od usera to raczej bym był za zwykłą metodą walidującą. Jeśli dane pochodzą z jakiejś aparatury i "złe dane" oznaczają że budynek ze sprzętem prawdopodobnie się pali (a to nie jest oprogramowanie od czujki pożarowej) to można rzucić wyjątkiem. Musisz pamiętać że rzucanie wyjątku to relatywnie kosztowna operacja i nie powinna sterować całkowicie zwykłym przepływem programu.


edytowany 4x, ostatnio: obscurity, 2020-07-04 08:39
Ja bym tak do końca nie demonizował tych nulli https://stackoverflow.com/a/175543 - bakunet 2020-07-04 08:40
przecież nie demonizuję żadnych nulli. Mówię o kodzie typu try {} catch (Exception) { return null; } wewnątrz biblioteki - obscurity 2020-07-04 08:41

Pozostało 580 znaków

2020-07-04 09:06

Rejestracja: 5 miesięcy temu

Ostatnio: 7 godzin temu

0

W tym wypadku zakładam, że dane z serwera powinny być za każdym razem poprawne, w razie gdy serwer z jakiegoś powodu zwróci nieprawidłowe dane, chcę w tej metodzie wyrzucić wyjątki.

Pozostało 580 znaków

2020-07-04 11:19

Rejestracja: 2 lata temu

Ostatnio: 3 godziny temu

Lokalizacja: Jastrzębie-Zdrój

0

Jaka jest różnica w rzuceniu wyjątkiem, a w zwyczajnym obsłużeniu ifa typu MessageBox albo IActionResult? Jeśli jakiś obiekt jest null to powinien to być wyjątek, czy informacja dla użytkownika - "ej, czegoś nie zaznaczyłeś, nie dodałeś, nie wpisałeś, zrób to jeszcze raz...", ponieważ ty wiesz co przekazać użytkownikowi w momencie gdy obiekt będzie null. Co jest takiego magicznego w wyjątkach? Moim zdaniem nic, a może być tak, że odwróci się to przeciwko tobie. Jeśli zaczniesz wszędzie wciskać wyjątki to skąd będziesz wiedział, który z nich jest twoim niedopatrzeniem (bugiem) w oprogramowaniu? Zakładasz, że nigdy nie zrobisz błędu w kodzie?

Pozostało 580 znaków

2020-07-04 11:33

Rejestracja: 5 miesięcy temu

Ostatnio: 7 godzin temu

2

Jaka jest różnica w rzuceniu wyjątkiem, a w zwyczajnym obsłużeniu ifa typu MessageBox albo IActionResult?

Moim zdaniem taka, że w przypadku danych od usera, spodziewasz się, że może wpisać dane nieprawidłowe(często i gęsto takie przypadki są prawdopodobne) - wtedy bez wyrzucania wyjątku.
Ale w sytuacjach typu błędne dane (które nie powinny mieć miejsca) z zewnętrznego serwera, czy błędna konfiguracja w configu, powinien być wyrzucony wyjątek

Pozostało 580 znaków

2020-07-04 12:02

Rejestracja: 2 lata temu

Ostatnio: 3 godziny temu

Lokalizacja: Jastrzębie-Zdrój

0

A to błędna konfiguracja w configu powinna rzucić wyjątkiem i już wtedy nie są to "dane nieprawidłowe", które można obsłużyć w sposób "normalny"? Pytanie tylko, czy to nie jest problem typu X Y? Dla mnie wyjątek to jest coś czego nie przewidziałem, coś co przeoczyłem. Od początku trzeba założyć, że użytkownik to debil i zacznie wklepywać do programu byle co. Według mnie, nie ma na to jednej odpowiedzi jak można, a jak powinno się to robić. Jesteś w stanie walidować dane użytkownika, to jesteś w stanie walidować dane z konfiguracji i wszystkich innych miejsc gdzie mogą być niepoprawne, błędne itp itd. A to co zwrócisz dalej, moim zdaniem, nie ma znaczenia. Znaczenie ma co może z tym zrobić użytkownik, programista, albo nawet sam program.

Pozostało 580 znaków

2020-07-04 13:07

Rejestracja: 2 lata temu

Ostatnio: 7 godzin temu

1

Jak już chcesz używać wyjątków to rób to z głową. Jeśli walidujesz argumenty na początku metody to throw New ArgumentNullException(nameof(obj) ). Albo inny silnie typowany wyjątek, który typem opisuje co się wywaliło (np własny dziedziczący po Exception). Wtedy możesz korzystać z osobnego catch dla każdego typu wyjątku. Message jest wyłącznie dla developera i leci do logów razem ze stack trace i innymi.
Wiadomość o błędzie dla użytkownika wrzucasz do resources i jakoś obslugujesz bo często z perspektywy użytkownika "validation error" jest bez sensu albo mylące.
Przyklad:
Lista api do których wysyłamy requesty:(IP, status, user, password) :

  • catch(ProtocolException e) => sprawdź czy to nie błąd uwierzytelnienia i obsłuż
  • catch(EnpointNotFound e) => ustaw status na offline
    -catch...
    -catch(Exception e) => masz buga, sprawdź, ale nie wysypuj całego programu.
edytowany 3x, ostatnio: chalwa, 2020-07-04 13:22
Pokaż pozostałe 5 komentarzy
Dla mnie jest zagadką, że @WeiXiao w większości swoich wpisów wstawia spolszczone angielskie słowa, ale jednocześnie bardzo lubi poprawiać innych gdy robią to samo :D - some_ONE 2020-07-04 15:52
@some_ONE: jest pewna subtelna różnica - authentication nie tłumaczy się na autentykacja, zresztą ja częściej wstawiam angielskie obok polskich, a nie tłumacze <wtf> - WeiXiao 2020-07-04 16:30
No nie tłumaczy, ale jedno i drugie dotyczy tego samego. Jak jest sensowny polski odpowiednik to po co na siłę używać angielskich słów (często jeszcze w dziwny sposób spolszczonych). - some_ONE 2020-07-04 17:00
autentykacja sensowna czy nie, jest raczej błędna. authentication jak już poprawiono = uwierzytelnienie. Po prostu false-friendly słówko. - WeiXiao 2020-07-04 17:01
Odpowiadasz tak jakbym twierdził że autentykacja to poprawne słowo. Ja w żaden sposób nie nawiązywałem do tego wpisu. - some_ONE 2020-07-04 18:13

Pozostało 580 znaków

2020-07-04 22:29

Rejestracja: 1 rok temu

Ostatnio: 3 godziny temu

0

ja tu tylko to zostawie https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why i to https://stackoverflow.com/questions/2184935/performance-cost-of-coding-exception-driven-development-in-java nie ważne, że java

nie widzę powodu dlaczego takiego zdarzenia if(obj==null) miałbyś nie obsłużyć w inny sposób

Pozostało 580 znaków

2020-07-05 02:15

Rejestracja: 9 lat temu

Ostatnio: 3 tygodnie temu

0

Sugeruję zrobić enuma z listą potencjalnych błędów i zwracać odpowiednie kody, rzucanie wyjątków to głupota, bo po pierwsze musisz i tak napisać kod, który obsługuje zwracane wartości z metody, a dodatkowo musisz napisać handler dla wyjątków (no chyba, że zostawiasz je rzucone luzem, co jest jeszcze głupsze), czyli de facto i tak obsługujesz jakąś awaryjną sytuację, tylko na dwa sposoby. Ułatw sobie życie, zrób to raz, do listy enumów szybko dodasz nowe kody błędów, a pisząc dłużej kod docenisz brak stosu handlerów w kodzie wywołującym.

Biblioteka standardowa .NET i wszystkie nugety z jakich korzystałem używały wyjątków. Jak chcesz zwracać kod błędu z metody, która zwraca obiekt? Wszystkie interfejsy musiałyby być podporządkowane do tego podejścia i trzeba by pisać dużo kodu sprawdzającego te kody. Mógłbyś podesłać projekt w którym jest to elegancko zrobione? - chalwa 2020-07-05 12:18
I to jest istne szaleństwo, żeby na każdy drobny błąd rzucać wyjątek. Wiem, że tak są niektóre rzeczy zaprojektowane, ale to nie znaczy, że trzeba za tym podążać jak ślepa owca na stracenie, jakbyś pisał wysokowydajny kod przetwarzający tonę danych i rzucałbyś wyjątkami wszędzie zamiast zwracać kody błędów nagle by się okazało, że twój kod działa wyjątkowo wolno. Co do metody, która zwraca obiekt, po to jesteś programistą żeby wiedzieć o takich rzeczach jak zwracanie wartości przez referencje. Zwracasz kod błędu i elegancko w switchu obsługujesz każdy z nich. - Bartosz Wójcik 2020-07-05 13:16
Zgadzam się, że nadużywanie wyjątków jest błędem, ale tak jak pisał @Kordoba operacje na plikach czy praca z zewnętrznym API w kodzie wysokiego poziomu najłatwiej obsłużyć wyjątkami. Warto zaznaczyć jakiego typu oprogramowanie piszemy jest różnica w podejściu przy pisaniu aplikacji użytkowej, bazy danych czy systemu wbudowanego. Argumenty ref to temat na inną dyskusję. - chalwa 2020-07-05 14:54
@chalwa: ale w tym przykładzie to void a druga sprawa, że możesz mieć bazowy obiekt który zawiera status zadania i generyczny wynik. Rzucenie wyjątkiem jest drogie - boska_cebula 2020-07-05 18:21
Prosty benchmark by odpowiedział wam niedowiarkom dlaczego nie warto używać wyjątków :) https://stackoverflow.com/a/9798675/12333655 - Bartosz Wójcik 2020-07-05 18:24
:O Sprawdziłem u siebie i rzeczywiście to jest zabójstwo dla wydajności. Będę to brał pod uwagę przy iterowaniu ;) - chalwa 2020-07-05 21:20

Pozostało 580 znaków

2020-07-05 23:21
Moderator

Rejestracja: 12 lat temu

Ostatnio: 5 godzin temu

Lokalizacja: Wrocław

3
Kordoba napisał(a):

Dodam że ify sprawdzają poprawność danych (otrzymanych od serwera jsona) i w przypadku gdy są niepoprawne (wchodzą w te instrukcje warunkowe) aplikacja nic nie może zrobić (ich niepoprawność jest krytyczna).

Proces sprawdzenia poprawności danych wejściowych nazywa się walidacją, a nie rzucaniem wyjątków.

Co o tym sądzicie? Powinienem tak rzucać wyjątkami w metodzie? Może jest inny powód dlaczego tak nie robić?

To, że dane z zewnętrznego serwera mogą być niekompletne jest oczywiste, a wyjątki jak sama nazwa wskazuje nie służą do obsługi sytuacji oczywistych.

Zauważ, że w ramach jednego obiektu wiele różnych właściwości może być błędnych, a przy swoim podejściu z wyjątkami wywalisz się na pierwszym problemie, czyli nie jesteś nawet w stanie na raz zwrócić całej informacji o tym, co jest nie tak z obiektem.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2020-07-06 00:17

Rejestracja: 4 lata temu

Ostatnio: 2 godziny temu

0

@somekind:

przy swoim podejściu z wyjątkami wywalisz się na pierwszym problemie, czyli nie jesteś nawet w stanie na raz zwrócić całej informacji o tym, co jest nie tak z obiektem.

to nie ma nic wspólnego z wyjątkami, równie dobrze mógłby zwrócić new ErrorResult("message") jak i również mógłby rzucić wyjątek po zebraniu rezultatu całej walidacji.

edytowany 5x, ostatnio: WeiXiao, 2020-07-06 00:20

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0