Właśnie przeglądałem jakiś kod, który napisałem jakiś czas temu i widzę, że mam kilka prywatnych metod, które generują argumentnullexceptions i / lub argumentexceptions, jeśli występują problemy z parametrami metod.
Wydaje mi się, że moim uzasadnieniem jest to, że pomaga w przyszłości sprawdzić aplikację, jeśli ktoś spróbuje „niewłaściwie użyć” tej metody w przyszłości. Jednak biorąc pod uwagę, że jest to metoda prywatna, a osoby, które mogą wywołać tę metodę, mogą zobaczyć powiązane komentarze i kod, po prostu nie trzeba jej rzucać. Na pewno nie zaszkodzi mieć je, choć dodaje bałaganu.
Mam wrażenie, że te wyjątki są na ogół bardziej przydatne w przypadku czegoś takiego jak interfejs API, który zostanie ujawniony publicznie.
źródło
Jak wszystko inne, zależy ...
Jeśli metody publiczne są prostymi opakowaniami, które wywołują metodę prywatną (na wzór prywatnej metody przeciążonej), sensowne może być zgłoszenie wyjątku w metodzie prywatnej zamiast sprawdzania każdej metody publicznej.
Zasadniczo, jeśli nie spełnia powyższej definicji, zwykle nie sprawdzałbym argumentów / nie rzucałbym wyjątku na metodę prywatną. Chociaż istnieją inne przypadki, generalnie robię to w metodzie prywatnej przed wykonaniem jakiejś kosztownej operacji, która może zakończyć się niepowodzeniem, jeśli argumenty są nieprawidłowe.
źródło
Zdaję sobie sprawę, że chociaż pytanie nie ma znacznika językowego, prawdopodobnie domyślnie mówi o „językach kawy”. Ale dla zachowania kompletności chciałbym wspomnieć o nieco rozbieżnym pozornym konsensusie w świecie C ++.
Są trzy rzeczy, którymi programiści C ++ zwykle będą się interesować:
noexcept
?W przeszłości podchodziłem do pierwszego problemu pisząc taki kod
gdzie
CHECK_ARGS
jest#define
d stałą czasową kompilacji, aby kompilator mógł całkowicie wyeliminować cały kod sprawdzający argumenty w zoptymalizowanych kompilacjach. (Nie twierdzę, że kompilacja czeków jest ogólnie dobrą rzeczą, ale uważam, że użytkownik powinien mieć możliwość ich skompilowania).Nadal podoba mi się to rozwiązanie, że kod sprawdzający argumenty jest wyraźnie widoczny w grupie
if
. Jednak druga i trzecia kwestia nie są przez to rozwiązane. Dlatego teraz bardziej skłaniam się ku użyciuassert
makra do sprawdzania argumentów.Standardy kodowania Boost są z tym zgodne:
Na CppCon'14 odbyła się bardzo interesująca rozmowa zatytułowana Defensive Programming Done Right ( część 1 , część 2 ). W pierwszej części swojego wystąpienia omawia teorię kontraktów i nieokreślonego zachowania. W drugiej części przedstawia bardzo dobrą propozycję systematycznego sprawdzania argumentów. Zasadniczo proponuje makra potwierdzające, które pozwalają użytkownikowi wybrać, jaki budżet (pod względem wykorzystania procesora) jest skłonny przekazać do biblioteki w celu sprawdzenia argumentów i sprawi, że biblioteka mądrze wykorzysta ten budżet. Dodatkowo użytkownik może zainstalować globalną funkcję obsługi błędów, która zostanie wywołana w przypadku wykrycia zerwanej umowy.
Jeśli chodzi o aspekt, że funkcja jest prywatna, nie sądzę, że oznacza to, że nigdy nie powinniśmy zmuszać jej do sprawdzania jej argumentów. Możemy bardziej ufać naszemu kodowi, aby nie naruszać kontraktu funkcji wewnętrznej, ale wiemy również, że nie jesteśmy doskonali. Sprawdzanie argumentów w funkcjach wewnętrznych jest tak samo pomocne w wykrywaniu własnych błędów, jak w funkcjach publicznych do wykrywania błędów w kodzie klienta.
źródło
Rozważ następującą strukturę:
Wewnętrzna logika: funkcja ta zakłada się, że jest wywoływana z poprawnymi parametrami, dlatego wykorzystuje twierdzenia do weryfikacji warunków wstępnych, końcowych i niezmiennych w celu sprawdzenia wewnętrznej logiki.
Interfejs użytkownika wrapper: Funkcja ta owija funkcję wewnętrzną i wykorzystuje InvalidArgumentExceptions do obsługi błędnych wartości i poinformować użytkownika, aby poprawić jego wejścia:
Assert(x).hasLength(4);
,Assume(y).isAlphanumeric();
,Assert(z).isZipCode();
,Assume(mailAdress).matchesRegex(regex_MailAdress);
,Reject(x).ifEmpty();
, itdOpakowanie interfejsu wsadowego: Ta funkcja otacza funkcję wewnętrzną i wykorzystuje rejestrowanie, oznaczenia ważności i statystyki do obsługi błędnych wartości bez przerywania długotrwałego zadania. Oznaczenia mogą być później używane przez osobę sprawdzającą i czyszczącą bazę wyników.
Opakowanie interfejsu wiersza poleceń: ta funkcja otacza funkcję wewnętrzną i ponownie prosi o ostatnie wejście.
Powinieneś używać zarówno - twierdzeń, jak i wyjątków - w różnych metodach dla różnych zadań. Należy oddzielić logikę wewnętrzną od sprawdzania parametrów. Porównaj to z rozdziałem Model, Widok, Kontroler.
źródło
Są lepsze sposoby na uniknięcie zerowego sprawdzania referencji: skorzystaj z kontraktu kodu lub struktury AOP, aby sprawdzić za Ciebie. Umowa Google „c # code” lub „postsharp”.
źródło