Widziałem to pytanie, ale mam jeszcze kilka pytań dotyczących użycia assert
słowa kluczowego. Rozmawiałem z kilkoma innymi programistami o użyciu assert
. W tym przypadku użycia istniała metoda, która może zwrócić wartość null, jeśli zostaną spełnione pewne wymagania wstępne. Kod, który napisałem, wywołuje metodę, a następnie zapewnia, że nie zwraca wartości null, i nadal używa zwróconego obiektu.
Przykład:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Teraz wyobraź sobie, że używam tego w ten sposób:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Powiedziano mi, że powinienem usunąć to assert
, że nigdy nie powinny być używane w kodzie produkcyjnym, tylko do testowania. Czy to prawda?
-ea
lub równoważnego.Objects.requireNonNull
Java 8).Odpowiedzi:
Użyj
Objects.requireNonNull(Object)
do tego.W twoim przypadku byłoby to:
Ta funkcja została stworzona do celów, o których wspomniałeś, tj. Wyraźnie zaznacz, co nie ma wartości zerowej; także w produkcji. Ogromną zaletą jest to, że upewniasz się, że znajdziesz wartości zerowe dokładnie tam, gdzie nie powinny występować. Będziesz miał mniej problemów z debugowaniem problemów spowodowanych zerowymi wartościami, które zostały przekazane gdzieś, gdzie nie powinny być.
Kolejną korzyścią jest dodatkowa elastyczność w zakresie kontroli zerowej w przeciwieństwie do
assert
. Chociażassert
jest słowem kluczowym do sprawdzania wartości logicznej,Objects.requireNonNull(Object)
jest funkcją i dlatego może być osadzony w kodzie o wiele bardziej elastyczny i czytelny. Na przykład:Należy pamiętać, że
Objects.requireNonNull(Object)
służy wyłącznie do sprawdzania wartości zerowej w przypadkuassert
uogólnienia.assert
ma nieco inne cele w tym względzie, tj. przede wszystkim testowanie. Musi być włączony, aby można go było włączyć do testowania i wyłączyć do produkcji. W każdym razie nie używaj go do kodu produkcyjnego. Może to spowolnić działanie aplikacji dzięki niepotrzebnym i skomplikowanym sprawdzeniom poprawności przeznaczonym do testowania. Użyj go, aby oddzielić kontrole tylko testowe od kontroli przeznaczonych również do produkcji.Sprawdź oficjalną dokumentację, aby uzyskać szczegółowe informacje na temat
assert
.źródło
Najważniejszą rzeczą, o której należy pamiętać, jest to, że można je wyłączyć, więc nigdy nie zakładaj, że zostaną wykonane.
Aby zapewnić zgodność wsteczną, JVM domyślnie wyłącza sprawdzanie poprawności asercji. Należy je jawnie włączyć za pomocą argumentu wiersza polecenia -enableassertions lub jego skrótu -ea:
Dlatego poleganie na nich nie jest dobrą praktyką.
Ponieważ asercje nie są domyślnie włączone, nigdy nie można zakładać, że zostaną wykonane, gdy zostaną użyte w kodzie. Dlatego zawsze powinieneś sprawdzać wartości puste i puste Opcjonalne, unikać używania asercji do sprawdzania danych wejściowych w publicznej metodzie, a zamiast tego używać niezaznaczonego wyjątku ... Zasadniczo wykonuj wszystkie kontrole tak, jakby tego nie było.
źródło
Na pewno powiedziano ci rażące kłamstwo. Dlatego.
Asercje są domyślnie wyłączone, jeśli po prostu uruchomisz autonomiczny plik Jvm. Gdy są wyłączone, mają zerową powierzchnię, dlatego nie będą miały wpływu na aplikację produkcyjną. Są jednak prawdopodobnie najlepszymi przyjaciółmi przy opracowywaniu i testowaniu kodu, a większość programów do testowania struktur szkieletowych umożliwia asercje (JUnit robi to), więc kod asercji jest wykonywany po uruchomieniu testów jednostkowych, pomagając wcześniej wykryć potencjalne błędy (np. możesz dodać potwierdzenia dla niektórych kontroli granic logiki biznesowej, co pomoże wykryć kod, który używa niewłaściwych wartości).
To powiedziawszy, jak sugeruje inna odpowiedź, właśnie z tego powodu (nie zawsze są one włączone) nie można polegać na zapewnieniach, aby wykonać niektóre istotne kontrole lub (szczególnie!) Utrzymać dowolny stan.
Aby zobaczyć ciekawy przykład użycia asercji, spójrz tutaj - na końcu pliku znajduje się metoda,
singleThreadedAccess()
która jest wywoływana z instrukcji assert w linii 201 i ma na celu przechwycenie potencjalnego dostępu wielowątkowego w testach.źródło
Inne odpowiedzi już wystarczająco dobrze to pokrywają, ale są też inne opcje.
Na przykład Spring ma metodę statyczną:
org.springframework.util.Assert.notNull(obj)
Istnieją również inne biblioteki z własnymi
Assert.something()
metodami. Bardzo łatwo jest także napisać własny.Pamiętaj jednak, jakie wyjątki zgłaszasz, jeśli jest to usługa internetowa. Poprzednia wspomniana metoda, na przykład, wyrzuca
IllegalArgumentException
domyślnie, który wiosną zwraca 500.W przypadku usługi internetowej często nie jest to wewnętrzny błąd serwera i nie powinien to być 500, ale 400, co jest złym żądaniem.
źródło
assert
to, aby natychmiast uzyskać awarię z wygenerowanym plikiem podstawowym, abyś mógł zrobić sekcję pośmiertną za pomocą swojego ulubionego debuggera w miejscu, w którym warunek został naruszony.assert
chce rzucić. Ciekawy. Wersja C / C ++ tego nie robi. Natychmiast podnosi sygnał, że a) zabija proces, i b) tworzy zrzut pamięci. Robi to z jakiegoś powodu: debugowanie takiego niepowodzenia nie jest łatwe, ponieważ nadal masz całą informację o stosie wywołań. Zdefiniowanieassert
zamiast tego rzucenia wyjątku, który następnie może zostać (nie) celowo zaprogramowany, pokonuje cel, imho.Throwable
. Zawsze można je złapać. Czy to dobrze, czy nie, nie wiem. Myślę, że to zależy. Wiele programów Java jest usługami sieciowymi i byłoby niepożądane, aby zawiesił się z prawie dowolnego powodu, więc prawie wszystko jest przechwytywane i rejestrowane. Jedną z wielkich rzeczy jest ślad stosu, który zwykle wystarcza do zdiagnozowania przyczyny wyjątku lub błędu.Używaj stwierdzeń swobodnie, ilekroć robi to, pomaga wychwycić błędy programowe, np. Błędy.
Nie używaj aser, aby przechwycić coś, co może się zdarzyć logicznie, np. Źle sformatowane dane wejściowe. Użyj potwierdzenia tylko wtedy, gdy błędu nie można naprawić.
Nie umieszczaj żadnej logiki produkcyjnej w kodzie, który jest uruchamiany, gdy sprawdzane jest potwierdzenie. Jeśli twoje oprogramowanie jest dobrze napisane, jest to trywialnie prawdziwe, ale jeśli nie, możesz mieć subtelne skutki uboczne i różne ogólne zachowanie z włączonymi i wyłączonymi asercjami.
Jeśli Twoja firma ma „kod testowy” i „kod produkcyjny”, które robią to samo, ale jako różne podstawy kodu (lub różne etapy edycji), wyjdź stamtąd i nigdy nie wracaj. Próba naprawienia tego poziomu niekompetencji jest prawdopodobnie stratą czasu. Jeśli Twoja firma nie umieści żadnych instrukcji aser poza kodem testów, uprzejmie powiedz im, że aserty są wyłączone w kompilacji produkcyjnej, a jeśli nie są, naprawienie tego błędu jest teraz Twoim priorytetem.
Wartość aserts powinna być dokładnie wykorzystywana w logice biznesowej, a nie tylko w pakiecie testowym. Ułatwia to przeprowadzanie wielu testów wysokiego poziomu, które nie muszą jawnie testować wielu rzeczy, aby przejść przez duże fragmenty kodu i wywołać wszystkie te twierdzenia. W kilku moich projektach typowe testy nawet nie potwierdziły niczego, po prostu nakazały wykonanie obliczeń na podstawie określonych danych wejściowych, co spowodowało sprawdzenie setek twierdzeń i znalezienie problemów nawet w małych kawałkach logiki w głębi.
źródło
Możesz użyć aser w dowolnym momencie. Nadchodzi debata, kiedy wykorzystać. Na przykład w przewodniku :
źródło