2009-08-14 14 views
46

Jaka jest różnica między obsługą wyjątków Javy a warunkami assert?Asemblacja wyjątku

Wiadomo, że Assert ma dwa typy. Ale kiedy powinniśmy użyć słowa kluczowego assert?

+0

Nie mogę uwierzyć własnym oczom: to pytanie zostało faktycznie edytowane przez użytkownika 166k i nadal wygląda tak! –

+1

Tak, całkiem źle. Sprzątałem to jeszcze trochę. Nie jestem pewien, co JavaResp ma na myśli, mówiąc "dwa typy". Domyślam się, że jest to warunek wstępny a post-kondycja według http://www.deitel.com/articles/java_tutorials/20060106/Assertions.html –

+0

"Jeszcze więcej", co oznacza "całą zmianę" w tym przypadku. – JakeSteam

Odpowiedz

72

Stosuj asercje dla wewnętrznych kontroli logicznych w kodzie oraz normalne wyjątki dla warunków błędu poza kontrolą Twojego bezpośredniego kodu.

Nie zapominaj, że asercje można włączać i wyłączać - jeśli zależy Ci na takich rzeczach, jak sprawdzanie poprawności argumentów, należy jawnie używać wyjątków. (Można jednak przeprowadzić walidację argumentów metodami prywatnych za pomocą asercji, ponieważ naruszenie w tym miejscu spowodowane jest wewnętrznym błędem, a nie zewnętrznym błędem.)

Alternatywnie jest to całkowicie uzasadnione (IMO), aby używać wyjątków do wszystkiego. Osobiście w ogóle nie używam twierdzeń, ale w pewnym stopniu jest to kwestia osobistych preferencji. (Z pewnością mogą istnieć obiektywne argumenty za i przeciw twierdzeniom, ale nie jest wystarczająco jasne, aby całkowicie usunąć preferencje.)

+4

Warto zauważyć, że niektóre języki faktycznie implementują asercje używające wyjątków. W takich językach twoje stwierdzenie, że "rozsądne jest używanie wyjątków dla wszystkiego" jest tak prawdziwe, że jest zbędne. :) – Imagist

+0

Zgodnie z określeniem [dasblinkenlight] (http://programmers.stackexchange.com/a/137167/175034): "Niezaznaczone wyjątki służą do wykrywania błędów programistycznych użytkowników biblioteki, a asercje służą do wykrywania błędów. w twojej własnej logice. To są oddzielne kwestie, które nie powinny być mieszane. " – MaxZoom

1

Twierdzenie służy wyłącznie do debugowania, a jego warunek wyzwalacza nie powinien wystąpić (wskaźnik zerowy, gdy nie powinno być etc.)

Wyjątek jest dla szczególnych zdarzeń systemowych, które zawsze mogą się zdarzyć: FileNotFound, ConnectionToServerLost itp

6

Wyjątkiem jest mechanizm sprawdzania, czy implementacja jest wykonywany bez oczekiwanych lub nieoczekiwanych błędów, czy nie. Widzimy więc, że wyjątki są używane do obsługi nawet nieprzewidzianych warunków podczas wykonywania aplikacji w lepszy sposób, a zatem używanie wyjątków skutecznie prowadzi do niezawodnej aplikacji.

Asercje nigdy nie powinny być częścią implementacji niektórych funkcji aplikacji. Powinny one być używane tylko do weryfikacji założeń - po to, aby mieć pewność, że wszystko, co zakładamy przy projektowaniu rozwiązania, jest rzeczywiście ważne również w praktyce.

referencyjny: http://geekexplains.blogspot.com/2008/06/asserions-in-java-assertions-vs.html

24

twierdzenia Java są zbudowane na szczycie wyjątków Java i obsługi wyjątków. Rzeczywiście, gdy asercja Java kończy się niepowodzeniem, wynikiem jest wyjątek AssertionError, który może zostać przechwycony jak każdy inny wyjątek Java. Główne różnice między wyjątków i twierdzeń są:

  • twierdzenia są przeznaczone być używane wyłącznie jako środek do wykrywania błędów programistycznych, aka błędów. Natomiast wyjątek może wskazywać na inne rodzaje błędów lub stan "wyjątkowy"; na przykład nieprawidłowe dane wejściowe użytkownika, brakujące pliki, sterty pełne i tak dalej.
  • Język Java zapewnia obsługę składniową asercji w postaci instrukcji assert. Porównaj następujące:

    if (x != y) { 
        throw new SomeException("x != y"); 
    } 
    
    assert x != y; 
    
  • najważniejsze, Java pozwala włączyć lub wyłączyć sprawdzanie twierdzenie globalnie lub w poszczególnych klasach po uruchomieniu JVM.

Uwaga: niektórzy mówią, że należy zawsze run kod produkcyjny z twierdzeniem sprawdzanie wyłączone.Nie zgadzam się z tym jako ogólnym stwierdzeniem. Jeśli twój kod produkcyjny jest znany jako stabilny ORAZ musisz wycisnąć z niego ostatnią część wydajności, wtedy wyłączenie asercji jest dobre. Ale jeśli (powiedzmy) 10% wydajności nie jest prawdziwym problemem, wolałbym, aby aplikacja zginęła z błędem potwierdzenia, jeśli alternatywa jest kontynuowana i uszkodzona jest moja baza danych.

@Mario Ortegón skomentował tak:

W „wyłączenie” dlatego twierdzenia mogą być wykorzystane do weryfikacji wyniku zoptymalizowanego algorytmu poprzez porównanie jej realizację przed znanym, ale powolny, algorytmu. Tak więc, w fazie rozwoju, można wywołać metodę O(N^3), aby stwierdzić, że algorytm O(log N) działa zgodnie z zamierzeniami. Ale to jest coś, czego nie chcesz produkować.

, czy nie uważasz, że to jest dobra praktykawyłączyć twierdzeń w produkcji, to z pewnością złą praktyką napisać twierdzeń, które mają znaczący wpływ na wydajność, gdy włączone. Czemu? Ponieważ oznacza to, że nie masz już możliwości włączania asercji w produkcji (śledzenie problemu) lub testów stresu/pojemności. Moim zdaniem, jeśli musisz wykonać O(N^3) testowanie przed/po kondycji, powinieneś zrobić to w swoich testach jednostkowych.

+0

"Wyłączenie" polega na tym, że można zastosować asercje w celu zweryfikowania wyniku zoptymalizowanego algorytmu, porównując jego implementację ze znanym, ale wolnym algorytmem. Tak więc, w fazie rozwoju, można wywołać tę metodę O (n3), aby potwierdzić, że algorytm O (log N) działa jako zamierzony ... Ale jest czymś, czego nie * chcesz * chcieć w produkcji. –

4

Przykład dobrego wykorzystania dochodzić:

assert flibbles.count() < 1000000; // too many flibbles indicate something is awry 
log.warning("flibble count reached " + flibbles.count()); // log in production as early warning 

Osobiście uważam, że Assert powinny tylko być stosowane, gdy wiesz, że coś jest poza pożądane limity, ale możesz być pewien, że to dość bezpieczne dalej. We wszystkich innych okolicznościach (nie zwracaj uwagi na okoliczności, o których nie myślałem) korzystaj z wyjątków, aby szybko i sprawnie zawieść.

Najważniejsza dla mnie kompromitacja to to, czy chcesz zniszczyć system Live/Production z wyjątkiem, aby uniknąć korupcji i ułatwić rozwiązywanie problemów, czy też napotkasz sytuację, która nigdy nie powinna być kontynuowana niezauważona w teście/wersje debugowania, ale można zezwolić na kontynuowanie produkcji (rejestrowanie ostrzeżenia oczywiście).

cf. http://c2.com/cgi/wiki?FailFast zobaczyć także moje C# kopię tej odpowiedzi: Debug.Assert vs. Specific Thrown Exceptions

+3

Asercje są znacznie * znacznie * silniejszymi stwierdzeniami. Mają one na celu udokumentowanie (i podczas uruchamiania w debugowaniu, aby zweryfikować) swoje założenia i/lub gwarancje dotyczące tego, co będzie zawsze prawdziwe w danym punkcie kodu. ** Asercje nigdy nie powinny się zdarzyć ** - jeśli tak się stanie, oznacza to, że (a) twoje założenia były błędne, i (b) od tego momentu nie można ufać, że zrobi się to, co trzeba (bo gdzieś wzdłuż linii, to * już zrobione * źle, a teraz działa "poza granicami"). – cHao

+0

Jeśli wiesz, że coś nigdy nie powinno się zdarzyć, to dlaczego pozwoliłeś mu przejść niezaznaczone w kodzie produkcyjnym, gdzie asercje są wyłączone? Z pewnością użyjesz wyjątku, aby upewnić się, że złamane założenie zostanie złapane. Wiem, że idę wbrew uzyskanej mądrości, ale chciałbym zobaczyć, jakie przekonywujące argumenty mogę odkryć, ponieważ są sprzeczne. Dzięki za komentarz! –

+1

Wyjątki dotyczą rzeczy, które normalnie nie występują, ale mogą. Brakujące pliki, awarie sieci, prawdopodobnie nieprawidłowe dane. Rzeczy, których twój kod nie może kontrolować. Twierdzenia dotyczą rzeczy, które, jeśli twój kod działa poprawnie, * nigdy * się nie dzieje. Są one przeznaczone do podwójnego sprawdzenia podczas debugowania. W produkcji Twój kod powinien już być wystarczająco pewny wyniku, którego nie musi już sprawdzać. – cHao

0

Twierdzenie używanego do debugowania wymaganych założeń mają być sprawdzane w czasie wykonywania tylko przez włączenie funkcji wymuszenia podczas Wyjątkiem jest sprawdzenie szczegółowych warunków, które należy sprawdzić podczas wykonywania program, aby zapobiec zakończeniu programu.

4

Asercje są bardzo podobne do wyjątków, tak jak wyjątki oznaczą problem, ale w przeciwieństwie do wyjątków - nie sugerują żadnej alternatywnej ścieżki wykonania, ale po prostu zawiodą. Dlaczego warto używać asercji, jeśli możesz zrobić to samo, a także więcej wyjątków?

Skorzystaj z nich, gdy problemy nie powinny zostać naprawione, a NIGDY NIGDY NIE NALEŻY STAĆ SIĘ NA PIERWSZYM MIEJSCU. Z początku brzmi to dziwnie: czy nie chcemy chronić naszego kodu przed WSZYSTKIMI potencjalnymi problemami? Zwykle tak. Ale jest przypadek, w którym nie mamy. Ta sprawa nazywa się: "Projektuj według umowy".

Powiedzmy, że piszesz wniosek do banku. Jako programista nie możesz wesprzeć wszystkich możliwych warunków finansowych. Zanim zaczniesz kodować, otrzymasz specyfikację od banku, która podaje prawidłowe zakresy, które ta aplikacja powinna obsługiwać. Więc twoja aplikacja jest zaprojektowana przez kontrakt (według specyfikacji z banku).Niniejsza umowa określi podstawowe zasady, które zawsze powinny być spełnione, aby Twoje zgłoszenie zadziałało. Te podstawowe zasady są nazywane "niezmiennikami" (ponieważ nie mogą się zmienić). Projektowanie przez umowę upraszcza Twoje życie jako programisty - jesteś odpowiedzialny tylko za wsparcie zakresu prac określonych w umowie.
Ważne jest, aby sprawdzić wartości tych niezmienników w kodzie, ale nie należy ich sprawdzać tak, jakby były wyjątkami i próbować je obejść. Jeśli są one złe - musisz ponieść porażkę, ponieważ dane wejściowe nie wypełniły zobowiązań umownych.

Interesujące jest to, że jeśli nie umieszczasz twierdzenia w krytycznym miejscu, a niezmienniki stają się nieważne - Twój kod i tak się powiedzie. Po prostu nie wiesz dlaczego. Podsumowując - do weryfikowania niezmienników wykorzystywane są asercje. Idą one ręka w rękę z zasadą "zaprojektuj według umowy". Użyj ich do debugowania problemu, dlatego wyłącza się je podczas produkcji.

Kolejny przypadek użycia: jeśli polegasz na zewnętrznej bibliotece, której nie ufasz całkowicie - możesz użyć instrukcji aser podczas jej wywoływania.

Niektórzy używają również twierdzeń jako szybkiego i brudnego zamiennika wyjątku (ponieważ jest to łatwe do wykonania), ale nie jest to właściwe podejście.