Używasz asercji zamiast rzucać wyjątkami?

38

Często, gdy piszę funkcje, chcę się upewnić, że dane wejściowe są prawidłowe, aby wykryć takie błędy jak najwcześniej (uważam, że są to tak zwane warunki wstępne). Kiedy warunek wstępny zawiedzie, zawsze rzucałem wyjątek. Ale zaczynam wątpić, czy jest to najlepsza praktyka, a jeśli nie, twierdzenia byłyby bardziej odpowiednie.

Więc kiedy mam to zrobić: kiedy należy zastosować stwierdzenie, a kiedy należy zgłosić wyjątek?

gablin
źródło
3
Myślę, że to pytanie powinno zostać zadane przy przepełnieniu stosu, chociaż prawdopodobnie zadawano je tam kilkanaście razy, więc możesz już tam znaleźć wiele odpowiedzi.
user281377,

Odpowiedzi:

50

Asercji należy używać wyłącznie do weryfikacji warunków, które z logicznego punktu widzenia nie mogą być fałszywe (czytaj: sprawdzanie rozsądku). Warunki te powinny opierać się wyłącznie na danych wejściowych wygenerowanych przez własny kod. Wszelkie kontrole oparte na danych zewnętrznych powinny wykorzystywać wyjątki.

Prostą zasadą, którą zwykle stosuję, jest weryfikowanie argumentów funkcji prywatnych za pomocą asercji i stosowanie wyjątków dla argumentów funkcji publicznych / chronionych.

Uwaga do samodzielnego wymyślenia imienia
źródło
Dobra uwaga na temat stosowania wyjątków dla zewnętrznych danych wejściowych. Do tego też dodam dane wyjściowe - problemy przy próbie utworzenia / zapisu do pliku / bazy danych itp.
ChrisF
13
I nieuchronnie przekonasz się, że te twierdzenia są wyzwalane w produkcji. +1 za weryfikację prywatnych rzeczy z zapewnieniami ! Może mógłbyś powiedzieć „użyj twierdzeń, gdy masz pełną kontrolę nad danymi wejściowymi”?
Frank Shearar
1
Przynajmniej w Javie zazwyczaj trzeba włączyć sprawdzanie asercji za pomocą parametru wiersza polecenia -ea. Oznacza to, że asercje są w zasadzie bez operacji, chyba że je wyraźnie włączysz.
Bill Michell,
29

Asercje służą do znajdowania błędów programistycznych. Twoje programy muszą działać równie dobrze, gdy wszystkie twierdzenia zostaną usunięte.

Z drugiej strony wyjątki dotyczą sytuacji, które mogą się zdarzyć nawet wtedy, gdy program jest doskonały; są spowodowane wpływami zewnętrznymi, takimi jak sprzęt, sieć, użytkownicy itp.

użytkownik 281377
źródło
Jest to całkiem dobry sposób na wyrażenie tego. Jeśli użytkownik wprowadzi coś nieprawidłowego, wyrzuć wyjątek. Jeśli dane wejściowe są prawidłowe, ale coś nadal jest nie tak, prześlij potwierdzenie.
Mateen Ulhaq
3

Typową praktyką programistyczną jest kompilowanie asercji z kompilacji produkcyjnych / wydania. Asercje pomogą tylko podczas testów wewnętrznych, aby uchwycić niepowodzenie założeń. Nie powinieneś zakładać zachowania zewnętrznych agencji, więc nie powinieneś twierdzić o zdarzeniach z sieci lub użytkownika. Dobrą praktyką jest również pisanie kodu obsługi kompilacji produkcyjnych w przypadku niepowodzenia asercji.

Na przykład w C

int printf(const char *fmt, ...)
{
  assert(fmt);  // may fail in debug build but not in production build
  if (!fmt) return -1; // handle gracefully in production build
  ...
}

Wyjątki mają być wbudowane w kompilacje produkcyjne. Alternatywą dla wyjątku jest zwracanie błędu, a nie asercji.

aufather
źródło
2
Nie sądzę, że dobrym pomysłem jest umieszczenie wdzięcznego zachowania za twierdzeniem o tym samym stanie. Nieuchronnie, ponieważ pełne wdzięku zachowanie istnieje tylko w wersji produkcyjnej, kod, który miał sobie z nim poradzić, zostanie źle przetestowany i ulegnie awarii tak samo źle, jak gdyby nie gorszy, gdyby kod nie był strzeżony.
Sebastian Redl
0

Jednym z problemów z twierdzeniami jest dla mnie to, że są one domyślnie wyłączone w Javie.

Stosujemy strategię pierwszego niepowodzenia, w której program - który mógł działać przez lata bez nadzoru - musi ulec awarii tak wcześnie, jak to możliwe, aby uniknąć uszkodzenia danych w przypadku złych danych (w nieoczekiwanej formie). Do tego używamy sprawdzania, a używając zapewnień, w zasadzie ryzykujemy, że nie będą aktywne.


źródło