Argumenty za lub przeciw używaniu Try / Catch jako operatorów logicznych [zamknięte]


36

Właśnie odkryłem piękny kod w naszej aplikacji firmowej, która używa bloków Try-Catch jako operatorów logicznych.
Oznacza to: „zrób jakiś kod, jeśli spowoduje to ten błąd, zrób ten kod, ale jeśli to spowoduje ten błąd, zrób tę trzecią rzecz zamiast tego”.
Używa słowa „Wreszcie” jako wyrażenia „else”.
Wiem, że z natury jest to niewłaściwe, ale zanim wybrałem walkę, liczyłem na dobrze przemyślane argumenty.
I hej, jeśli masz argumenty przemawiające za użyciem Try-Catch w ten sposób, proszę powiedz.

Dla każdego, kto się zastanawia, językiem jest C #, a kod ma około 30+ linii i szuka konkretnych wyjątków, nie obsługuje WSZYSTKICH wyjątków.


13
Mam tylko argumenty przeciwko tej praktyce, a ponieważ wydajesz się już przekonany, że to zły pomysł, nie zamierzam zawracać sobie głowy publikowaniem ich.
FrustratedWithFormsDesigner

15
@FrustratedWIthFormsDesigner: To złe rozumowanie. Co z ludźmi, którzy nie są przekonani? Co z moim faktycznym pytaniem, w którym konkretnie pytam o powody, ponieważ tak naprawdę nie mogę powiedzieć „dlaczego”, po prostu wiem, że to jest złe.
James P. Wright,

3
Moje opinie zależą w dużej mierze od tego, co faktycznie robi dany kod. Są rzeczy, które nie mogą być wcześniej sprawdzone (lub nie pozwalają na warunki wyścigu podczas próby, takie jak wiele operacji na plikach - w opóźnieniu między sprawdzaniem a operacją, wszystko może się zdarzyć z plikiem) i muszą być try„d. Nie każdy wyjątkowy przypadek, który ogólnie uzasadnia wyjątek, musi być śmiertelny w tym konkretnym przypadku. Czy mógłbyś to zrobić w prostszy, jednakowy lub bardziej niezawodny sposób bez wyjątków?

11
Mam nadzieję, że tak naprawdę nie używają bloku „w końcu” jako „innego”, ponieważ blok „w końcu” jest zawsze uruchamiany po poprzednim kodzie, niezależnie od zgłaszanych wyjątków.
jimreed

2
Jakiego języka używają? Jest doskonale w, powiedzmy, OCaml, gdzie standardowa biblioteka rutynowo zgłasza wyjątki. Obsługa wyjątków jest tam bardzo tania. Ale to nie będzie tak wydajne w CLI lub JVM.
SK-logic

Odpowiedzi:


50

Obsługa wyjątków jest zwykle drogim sposobem obsługi kontroli przepływu (z pewnością w języku C # i Javie).

Środowisko wykonawcze wykonuje dość dużo pracy, gdy konstruowany jest obiekt wyjątku - gromadzenie śladu stosu, ustalenie, gdzie obsługiwany jest wyjątek i więcej.

Wszystkie te koszty pamięci i zasobów procesora, których nie trzeba rozszerzać, jeśli do sterowania przepływem używane są instrukcje kontroli przepływu.

Ponadto istnieje problem semantyczny. Wyjątki dotyczą wyjątkowych sytuacji, a nie normalnej kontroli przepływu. Do obsługi nieprzewidzianych / wyjątkowych sytuacji należy używać obsługi wyjątków, a nie zwykłego przepływu programu, ponieważ w przeciwnym razie nieprzechwycony wyjątek powie znacznie mniej.

Oprócz tych dwóch, kwestią są inne osoby czytające kod. Używanie wyjątków w taki sposób nie jest czymś, czego spodziewa się większość programistów, więc cierpi na czytelności i zrozumiałości kodu. Kiedy widzi się „wyjątek”, myśli się - stało się coś złego, coś, co nie powinno się normalnie zdarzyć. Tak więc stosowanie wyjątków w ten sposób jest po prostu mylące.


1
Dobra uwaga na temat wydajności, choć zależy to również od specyfiki platformy.
FrustratedWithFormsDesigner

4
Jeśli to jedyna wada, dziękuję - zrezygnuję z wydajności każdego dnia, jeśli kupi mi lepszy kod (z wyjątkiem ścieżek krytycznych pod względem wydajności, to znaczy; ale na szczęście jest to tylko 20% całego kodu nawet w aplikacjach, które są ogólnie wydajne -krytyczny).

5
@delnan - Nie, nie jedyny minus.
Oded

2
Poza słowem nieprzypisane Zgadzam się z twoim postem. W twoim kodzie zdarzają się wyjątki. Większość z nich powinna być przewidywalna, np. Awarie połączenia z bazą danych lub zgłoszenie serwisowe lub w dowolnym momencie w przypadku niezarządzanego kodu. Łapiesz problemy poza twoją kontrolą i sobie z nimi radzisz. Ale zgadzam się, że nigdy nie powinieneś mieć kontroli przepływu opartej na wyjątkach, których możesz uniknąć w swoim kodzie.
SoylentGray

4
„Obsługa wyjątków jest zwykle drogim sposobem obsługi kontroli przepływu”. Fałsz dla Pythona.
S.Lott,

17

Właśnie odkryłem piękny kod w naszej aplikacji firmowej, która używa bloków Try-Catch jako operatorów logicznych. Oznacza to: „zrób jakiś kod, jeśli spowoduje to ten błąd, zrób ten kod, ale jeśli to spowoduje ten błąd, zrób tę trzecią rzecz zamiast tego”. Używa słowa „Wreszcie” jako wyrażenia „else”. Wiem, że z natury jest to błędne ...

Skąd to wiesz? Zrezygnowałem z tego rodzaju „wiedzy” i teraz po prostu wierzę, że najprostszy kod jest najlepszy. Załóżmy, że chcesz przekonwertować ciąg na opcjonalny, który jest pusty, jeśli parsowanie się nie powiedzie. Nie ma nic złego w:

try { 
    return Optional.of(Long.valueOf(s)); 
} catch (NumberFormatException) { 
    return Optional.empty(); 
}

Całkowicie nie zgadzam się ze zwykłą interpretacją „wyjątków dotyczą wyjątkowych warunków”. Jeśli funkcja nie może zwrócić użytecznej wartości lub metoda nie może spełnić warunków dodatkowych, należy zgłosić wyjątek. Nie ma znaczenia, jak często te wyjątki są zgłaszane, dopóki nie zostanie wykazany problem z wydajnością.

Wyjątki upraszczają kod, umożliwiając oddzielenie obsługi błędów od normalnego przepływu. Po prostu napisz najprostszy możliwy kod, a jeśli łatwiej jest użyć try-catch lub zgłosić wyjątek, zrób to.

Wyjątki upraszczają testowanie, zmniejszając liczbę ścieżek w kodzie. Funkcja bez rozgałęzień albo zakończy działanie, albo zgłosi wyjątek. Funkcja z wieloma ifinstrukcjami do sprawdzania kodów błędów ma wiele możliwych ścieżek. Bardzo łatwo jest pomylić jeden z warunków lub całkowicie go zapomnieć, aby niektóre warunki błędu zostały zignorowane.


4
Myślę, że to naprawdę niezły argument. Twój kod jest czysty i zwięzły i ma sens w tym, co robi. W rzeczywistości jest to podobne do tego, co dzieje się w kodzie, który widzę, tyle że jest o wiele bardziej złożony, jest zagnieżdżony i obejmuje ponad 30 linii kodu.
James P. Wright,

@James: wygląda na to, że kod byłby w porządku, gdybyś wyodrębnił kilka mniejszych metod.
kevin cline,

1
Można argumentować, że Java naprawdę może użyć czegoś bardziej jak TryParse C #. W języku C # będzie to kod int i; if(long.TryParse(s, out i)) return i; else return null;. TryParse zwraca false, jeśli ciąg nie mógł zostać przeanalizowany. Jeśli można go przeanalizować, ustawia argument wyjściowy na wyniki analizy i zwraca true. Nie występują wyjątki (nawet wewnętrznie w TryParse), a zwłaszcza żadnych wyjątków typu oznaczającego błąd programisty, jak FormatExceptionzawsze .NET .
Kevin Cathcart,

1
@Kevin Cathcart, ale dlaczego tak jest lepiej? kod wychwytujący wyjątek NumberFormatException jest dla mnie o wiele bardziej oczywisty niż sprawdzanie wyniku TryParse pod kątem wartości null.
Winston Ewert

1
@ChrisMiskowiec, podejrzewam, który z nich jest dla ciebie bardziej zrozumiały, jest w zasadzie kwestią tego, do czego jesteś przyzwyczajony. Uważam, że złapanie wyjątku jest dużo łatwiejsze do naśladowania niż sprawdzanie magicznych wartości. Ale to wszystko subiektywne. Obiektywnie uważam, że powinniśmy preferować wyjątki, ponieważ mają rozsądną wartość domyślną (zawieszają program), a nie domyślną, która ukrywa błąd (kontynuuj, jakby nic się nie stało). Prawdą jest, że .NET działa słabo z wyjątkami. Ale to wynik projektu .NET, a nie natura wyjątków. Jeśli w .NET, tak, musisz to zrobić. Ale w zasadzie wyjątki są lepsze.
Winston Ewert

12

Debugowanie i prace konserwacyjne są bardzo trudne, gdy przepływ sterowania jest wykonywany z wykorzystaniem wyjątków.

Z natury wyjątki zaprojektowano jako mechanizm zmiany normalnego przepływu sterowania programem - wykonywania nietypowych czynności, powodujących nietypowe skutki uboczne, jako sposób na wyjście ze szczególnie ciasnego powiązania, którego nie da się poradzić z mniej skomplikowanymi znaczy. Wyjątki są wyjątkowe. Oznacza to, że w zależności od konkretnego środowiska, w którym pracujesz, użycie wyjątku dla regularnego przepływu kontroli może spowodować:

  • Niewydolność Dodatkowe obręcze, przez które środowisko musi przejść, aby bezpiecznie wykonać stosunkowo trudne zmiany kontekstu wymagane dla wyjątków, wymagają oprzyrządowania i zasobów.

  • Trudności debugowania Czasami przydatne (podczas próby debugowania programu) informacje są wyrzucane przez okno, gdy występują wyjątki. Możesz stracić kontrolę nad stanem programu lub historią, które są istotne dla zrozumienia zachowania w czasie wykonywania

  • Problemy konserwacyjne Przebieg wykonania jest trudny do przejścia przez skoki wyjątków. Poza tym wyjątek może zostać wygenerowany z kodu typu czarnej skrzynki, który może nie zachowywać się w sposób łatwy do zrozumienia podczas zgłaszania wyjątku.

  • Słabe decyzje projektowe Programy zbudowane w ten sposób zachęcają do myślenia, które w większości przypadków nie jest łatwe do eleganckiego rozwiązania problemów. Złożoność końcowego programu zniechęca programistę do pełnego zrozumienia jego wykonania i zachęca do podejmowania decyzji, które prowadzą do krótkoterminowych ulepszeń przy wysokich kosztach długoterminowych.


10

Widziałem ten wzór używany kilka razy.

Istnieją 2 główne problemy:

  • Jest niezwykle drogi (tworzenie instancji obiektu wyjątku, gromadzenie stosu wywołań itp.). Niektóre kompilatory mogą być w stanie zoptymalizować go, ale nie liczyłbym na to w tym przypadku, ponieważ wyjątki nie są przeznaczone do takiego zastosowania, dlatego nie można oczekiwać, że ludzie będą go optymalizować.
  • Używanie wyjątków do sterowania przepływem jest w rzeczywistości skokiem, podobnie jak goto. Skoki są uważane za szkodliwe z wielu powodów. Powinny być stosowane, jeśli wszystkie alternatywy mają znaczące wady. W rzeczywistości w całym moim kodzie pamiętam tylko 2 przypadki, w których skoki były zdecydowanie najlepszym rozwiązaniem.

2
Po prostu umieszczenie go tam, jeśli / else jest również uważane za skok. Różnica polega na tym, że jest to skok, który może wystąpić tylko w tym konkretnym miejscu (i czyta się o wiele łatwiej) i nie musisz się martwić o nazwy etykiet (których nie musisz próbować / łapać , ale w porównaniu do goto). Ale samo powiedzenie „to skok, co jest złe” mówi również, że jeśli / else jest zły, kiedy nie jest.
jsternberg,

1
@jsternbarg: Tak, jeśli / else są faktycznie skompilowane do skoków na poziomie maszyny, ale na poziomie języka cel skoku jest następną instrukcją, podczas gdy w przypadku pętli jest to bieżąca instrukcja.
Twierdziłbym

9

Czasami wyjątki są najszybsze. Widziałem przypadki, w których wyjątki zerowych obiektów były szybsze nawet w Javie niż użycie struktur kontrolnych (w tej chwili nie mogę cytować badania, więc musisz mi zaufać). Problem pojawia się, gdy Java musi poświęcić trochę czasu i zapełnić ślad stosu niestandardowej klasy wyjątku zamiast używać rodzimych (które wydają się przynajmniej częściowo buforowane). Zanim powiesz, że coś jest jednostronnie szybsze lub wolniejsze, dobrze byłoby przeprowadzić test porównawczy.

W Pythonie jest nie tylko szybsze, ale bardziej poprawne jest zrobienie czegoś, co może spowodować wyjątek, a następnie obsłużenie błędu. Tak, możesz wymusić system typów, ale jest to sprzeczne z filozofią języka - zamiast tego powinieneś po prostu wywołać metodę i złapać wynik! (Testowanie, czy plik jest zapisywalny, jest podobne - po prostu spróbuj do niego zapisać i wychwyć błąd).

Widziałem czasy, kiedy szybsze jest robienie czegoś głupiego, jak tabele zapytań, których nie było, niż stwierdzenie, czy tabela istnieje w PHP + MySQL ( pytanie, w którym porównuję, jest to właściwie moja jedyna zaakceptowana odpowiedź z negatywnymi głosami) .

Wszystko to mówi, że stosowanie wyjątków powinno być ograniczone z kilku powodów:

  1. Przypadkowe połknięcie zagnieżdżonych wyjątków. To jest najważniejsze. Jeśli złapiesz jakiś głęboko zagnieżdżony wyjątek, z którym ktoś próbuje sobie poradzić, właśnie postrzeliłeś kolegę programistę (może nawet ciebie!) W stopę.
  2. Testy stają się nieoczywiste. Blok kodu, który ma wyjątek, może mieć jedną z kilku wad. Z drugiej strony wartość logiczna, choć teoretycznie debugowanie może być denerwujące, ale ogólnie nie jest. Jest to szczególnie prawdziwe, ponieważ try...catchzwolennicy kontroli przepływu ogólnie (z mojego doświadczenia) nie postępują zgodnie z filozofią „minimalizuj kod w bloku prób”.
  3. Nie pozwala na else ifblok. Wystarczy powiedzieć (a jeśli ktoś skontaktuje się z „Ale mógłby użyć różnych klas wyjątków”, moja odpowiedź brzmi: „Idź do swojego pokoju i nie wychodź, dopóki nie pomyślisz o tym, co powiedziałeś”).
  4. Jest to gramatycznie wprowadzające w błąd. Exception, dla reszty świata (ponieważ nie jest zwolennikiem try...catchfilozofii kontroli przepływu), oznacza, że ​​coś weszło w niestabilny (choć być może możliwy do odzyskania) stan. Niestabilne stany są ZŁE i powinno nas wszystkich utrzymywać w nocy, jeśli rzeczywiście mamy wyjątki, których można uniknąć (tak naprawdę to mnie przeraża, żadnych kłamstw).
  5. Nie jest zgodny ze wspólnym stylem kodowania. Naszym zadaniem, zarówno przy użyciu naszego kodu, jak i interfejsu użytkownika, jest uczynienie świata tak oczywistym, jak to możliwe. try...catchkontrola przepływu jest sprzeczna z powszechnie uznawanymi najlepszymi praktykami. Oznacza to, że nauka nowego projektu zajmuje więcej czasu, co oznacza wzrost liczby osobogodzin bez absolutnie żadnego zysku.
  6. Często prowadzi to do duplikacji kodu. Wreszcie bloki, choć nie jest to absolutnie konieczne, muszą rozwiązać wszystkie wiszące wskaźniki, które zostały otwarte przez przerwany blok try. Więc spróbuj bloków. Oznacza to, że możesz mieć try{ obj.openSomething(); /*something which causes exception*/ obj.doStuff(); obj.closeSomething();}catch(Exception e){obj.closeSomething();}. W bardziej tradycyjnym if...elsescenariuszu closeSomething()jest mniej prawdopodobne (ponownie, osobiste doświadczenie), że będzie to zadanie kopiowania i wklejania. (Trzeba przyznać, że ten konkretny argument ma więcej wspólnego z ludźmi, których spotkałem, niż z samą filozofią).

AFAIK, # 6 jest problemem tylko w Javie, która, w przeciwieństwie do każdego innego współczesnego języka, nie ma zamknięć ani zarządzania zasobami opartego na stosie. Z pewnością nie jest to problem związany ze stosowaniem wyjątków.
kevin cline,

4 i 5 wydają mi się tym samym punktem. 3-6 nie mają zastosowania, jeśli Twoim językiem jest Python. 1 i 2 są potencjalnymi problemami, ale myślę, że można je rozwiązać, minimalizując kod w bloku try.
Winston Ewert

1
@Winston Nie zgadzam się. 1 i 2 są głównymi problemami, które, choć pomniejszone przez lepsze standardy kodowania, wciąż zastanawiają się, czy nie lepiej byłoby po prostu uniknąć potencjalnego błędu na początku. 3 ma zastosowanie, jeśli Twoim językiem jest Python. 4-5 mogą również ubiegać się o Python, ale nie muszą. 4 i 5 to bardzo różne punkty - wprowadzanie w błąd różni się od różnic stylistycznych. Wprowadzający w błąd kod może na przykład nazywać wyzwalacz, aby uruchomić pojazd, „przycisk stop”. Z drugiej strony stylistycznie mogłoby to być analogiczne do unikania wszystkich wcięć blokowych w C.
cwallenpoole

3) Python ma inny blok wyjątków. Jest to bardzo pomocne w unikaniu problemów, które zwykle występują w przypadku 1 i 2.
Winston Ewert

1
Dla jasności, nie zalecam używania wyjątków, które są twoim ogólnym mechanizmem kontroli przepływu. Opowiadam się za wprowadzeniem wyjątku dla każdego rodzaju trybu „awarii”, bez względu na to, jak niewielki. Myślę, że wersja obsługi wyjątków jest czystsza i rzadziej ukrywa błędy niż wersja sprawdzająca wartość zwracaną. I idealnie, chciałbym, aby języki utrudniały wykrywanie zagnieżdżonych błędów.
Winston Ewert

4

Moim głównym argumentem jest to, że użycie try / catch dla logiki przerywa logiczny przepływ. Podążanie za „logiką” poprzez konstrukcje nielogiczne jest (dla mnie) sprzeczne z intuicją i mylące. Przyzwyczaiłem się czytać moją logikę jako „jeśli Warunek to A jeszcze B”. Czytanie tego samego zdania, co „Spróbuj złapać, a następnie wykonać B” wydaje się dziwne. Byłoby jeszcze dziwniejsze, gdyby instrukcja Abyła prostym przypisaniem, wymagającym dodatkowego kodu, aby wymusić wyjątek, jeśli conditionjest fałszywy (a zrobienie tego prawdopodobnie wymagałoby if-statement i tak).


2

Cóż, to kwestia etykiety, zanim „zaczniesz z nimi kłócić się”, jak sam twierdzisz, uprzejmie zapytałbym: „Dlaczego używają obsługi wyjątków w tych różnych miejscach?”.

Mam na myśli kilka możliwości:

  1. są niekompetentni
  2. istnieje całkowicie uzasadniony powód tego, co zrobili, który może nie pojawić się na pierwszy rzut oka.
  3. czasami jest to kwestia gustu i może uprościć skomplikowany przebieg programu.
  4. To relikt przeszłości, którego nikt jeszcze nie zmienił i byliby szczęśliwi, gdyby ktoś to zrobił

... Myślę, że wszystkie z nich są jednakowo prawdopodobne. Zapytaj ich więc ładnie.


1

Try Catch powinien być używany tylko do obsługi wyjątków. Co więcej, specjalna obsługa wyjątków. Twój try catch powinien wychwycić tylko oczekiwane wyjątki, w przeciwnym razie nie jest dobrze uformowany. Jeśli potrzebujesz użyć catch all try catch, prawdopodobnie robisz coś złego.

EDYTOWAĆ:

Powód: Możesz argumentować, że jeśli użyjesz try catch jako operatora warunkowego, jak zamierzasz uwzględnić PRAWDZIWE wyjątki?


2
OP pyta o powody / argumenty. Nie podałeś żadnych.
Oded

„Można argumentować, że jeśli użyjesz try catch jako operatora warunkowego, jak zamierzasz uwzględnić PRAWDZIWE wyjątki?” - Łapiąc te prawdziwe wyjątki w catchklauzuli innej niż ta, która łapie „nierealne” wyjątki?

@delnan - Dziękujemy! udowodniłeś punkt, który chciałem poruszyć. Gdyby ktoś odpowiedział na to, co przed chwilą powiedziałeś, zarówno mojemu, jak i Odedowi, przestałbym mówić, ponieważ nie szuka powodów, dla których jest uparty i nie marnuję czasu uporem.
AJC

Nazywasz mnie studdborn, ponieważ wskazuję wady niektórych z wymienionych tutaj argumentów? Zwróć uwagę, że nie mam nic do powiedzenia w stosunku do innych punktów tutaj podanych. Nie jestem fanem używania wyjątków do kontroli przepływu (chociaż nie potępię niczego też bez szczegółów, stąd moje zapytanie o opracowanie przez OP), gram jedynie adwokata diabła.

1
Używanie try-catch jako operatora warunkowego w żaden sposób nie uniemożliwia mu działania w celu wychwycenia „prawdziwych” wyjątków.
Winston Ewert

1

Wyjątek dotyczy sytuacji wyjątkowej. Czy program działa zgodnie ze zwykłym przepływem pracy?


1
Ale dlaczego? Chodzi o pytanie, dlaczego (lub dlaczego nie) wyjątki są do tego dobre.
Winston Ewert

Nie zawsze „wyjątkowy”. Na przykład nie znalezienie klucza w tablicy haszującej nie jest wyjątkowe, a jednak biblioteka OCaml zwykle podnosi wyjątek w takich przypadkach. I jest w porządku - obsługa wyjątków jest tam bardzo tania.
SK-logic,

1
-1: oświadczenie tautologiczne
Ciastka z mąki ryżowej,

1

Powód zastosowania wyjątków:

  1. Jeśli zapomnisz złapać wyjątkową okoliczność, twój program umrze, a ślad stosu powie ci dokładnie, dlaczego. Jeśli zapomnisz obsłużyć wartość zwracaną w wyjątkowych okolicznościach, nie powiesz, jak daleko twój program będzie wykazywał nieprawidłowe zachowanie.
  2. Korzystanie z wartości zwracanych działa tylko wtedy, gdy istnieje wartosc wartosci, którą możesz zwrócić. Jeśli wszystkie możliwe wartości zwracane są już prawidłowe, co zamierzasz zrobić?
  3. Wyjątek zawiera dodatkowe informacje o tym, co się wydarzyło, które mogą być przydatne.

Powody, dla których nie należy stosować wyjątków:

  1. Wiele języków nie zostało stworzonych w celu szybkiego wprowadzania wyjątków.
  2. Wyjątki, które przemieszczają się o kilka warstw w górę stosu, mogą pozostawić niespójny stan

Na końcu:

Celem jest napisanie kodu informującego o tym, co się dzieje. Wyjątki mogą pomóc / utrudnić to w zależności od tego, co robi kod. Próba złapania w Pythonie dla KeyError w odwołaniu do słownika jest doskonale (o ile znasz język) próba / catch dla tej samej KeyError oddalonej o pięć warstw funkcji jest niebezpieczna.


0

W niektórych sytuacjach używam try-> catch jako kontroli przepływu. Jeśli twoja podstawowa logika zależy od czegoś, co się nie powiedzie, ale nie chcesz po prostu rzucić wyjątek i wyjść ... Po to jest blok try-> catch. Piszę wiele niemonitorowanych skryptów unixowych po stronie serwera, a ich o wiele ważniejsze jest, aby nie zawiodły, niż by ładnie zawiodły.

Więc spróbuj Plan A, a jeśli umrze, planowanie połowów i biegać z Planu B ... A jeśli nie Plan B, wykorzystanie wreszcie skopać Plan C, który będzie albo jeden fix z nieudanych usług w A lub B, lub na stronie mnie.


0

Zależy to od języka i być może od zastosowanej implementacji. Standardem w C ++ jest zapisywanie wyjątków dla naprawdę wyjątkowych wydarzeń. Z drugiej strony, w Pythonie jedną ze wskazówek jest „ łatwiej prosić o wybaczenie niż o pozwolenie ”, dlatego zachęca się do integracji bloków try / oprócz w logice programu.


„Standardem w C ++ jest to, że należy zachować wyjątki dla naprawdę wyjątkowych wydarzeń.” To nonsens. Nawet wynalazca języka nie zgadza się z tobą .
arayq2

-1

To zły nawyk, ale robię to od czasu do czasu w Pythonie. Zamiast sprawdzać, czy plik istnieje, po prostu próbuję go usunąć. Jeśli rzuca wyjątek, łapię i po prostu przechodzę dalej wiedząc, że go nie ma. <== (niekoniecznie prawda, jeśli inny użytkownik jest właścicielem pliku, ale robię to w katalogu osobistym użytkownika, więc NIE POWINIEN się zdarzyć).

Nadużywane to zła praktyka.


3
W tym przykładzie użycie wyjątków zamiast „patrzenia przed skokiem” jest właściwie dobrym pomysłem: pozwala uniknąć warunków wyścigowych. Sprawdzenie dostępności pliku (istnienie, uprawnienia, niezablokowanie) powodzenie nie oznacza później - nawet jeśli to tylko kilka kodów później - dostęp (otwieranie, usuwanie, przenoszenie, blokowanie, cokolwiek) zostanie zwiększony, tak jak plik być zmieniany (usuwany, przenoszony, zmiany uprawnień) pomiędzy.

Jeśli python zgłasza wyjątek tylko dlatego, że plik nie istnieje, wydaje się zachęcać do złych nawyków, jak opisuje delnan.
Per Johansson,

@delnan: Chociaż prawdą jest, że IMHO, jeśli napotkasz takie warunki wyścigowe, jest prawdopodobne, powinieneś przemyśleć swój projekt. W takim przypadku w twoich systemach wyraźnie brakuje rozdzielenia problemów. O ile nie masz bardzo dobrych powodów, aby robić to w ten sposób, powinieneś ujednolicić dostęp na swoim komputerze lub użyć odpowiedniej bazy danych do obsługi wielu klientów próbujących wykonać transakcje na tych samych trwałych danych.
back2dos

1
To nie jest zły nawyk. Jest to zalecany styl w Pythonie.
Winston Ewert,

@ back2dos, czy można temu zapobiec w przypadku zasobów zewnętrznych, takich jak inni użytkownicy bazy danych / systemu plików?
Winston Ewert

-1

Podoba mi się sposób, w jaki Apple to definiuje : wyjątki dotyczą tylko błędów programisty i krytycznych błędów środowiska wykonawczego. W przeciwnym razie użyj kodów błędów. Pomaga mi zdecydować, kiedy go użyć, myśląc sobie: „Czy to błąd programisty?”


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.