C # - co robi metoda Assert ()? Czy nadal jest przydatne?

156

Debuguję z punktami przerwania i zdaję sobie sprawę z wywołania assert? Myślałem, że to tylko do testów jednostkowych. Co robi więcej niż punkt przerwania? Skoro mogę ustawić punkt przerwania, dlaczego powinienem używać funkcji Assert?

Pokus
źródło
9
Przy okazji, jeśli interesują Cię potwierdzenia, zdecydowanie powinieneś zagłębić się w kontrakty kodu .
MasterMastic
Możliwy duplikat stackoverflow.com/questions/129120/ ...
Michael Freidgeim

Odpowiedzi:

200

W kompilacji debugowania Assertprzyjmuje warunek logiczny jako parametr i wyświetla okno dialogowe błędu, jeśli warunek jest fałszywy. Program przebiega bez przerwy, jeśli warunek jest spełniony.

Jeśli kompilujesz w Release, wszystkie Debug.Assertsą automatycznie pomijane.

Patrick Desjardins
źródło
12
jak mogę uzyskać takie samo zachowanie Debug.Assert w trybie wydania?
Hamish Grubijan
15
Trace.Assert for release mode najwyraźniej odnosił się do: msdn.microsoft.com/en-us/library/… msdn.microsoft.com/en-us/library/e63efys0.aspx
Tim Abell
8
@HamishGrubijan A dlaczego miałbyś chcieć Debug.Assertw trybie wydania?
Camilo Martin,
25
IMO, pomijanie potwierdzeń w kodzie dopuszczenia jest jak przeprowadzanie ćwiczeń łodzi ratunkowej podczas zadokowania, a następnie pozostawianie łodzi ratunkowych za sobą podczas żeglugi. :)
chrisd
113
Asserts to nie łódź ratunkowa, to system wykrywania gór lodowych. Ponieważ użytkownik nie steruje statkiem, potwierdzenie w kodzie wydania mówi mu tylko, że jest skazany na zagładę; nie pozwala im uniknąć góry lodowej.
Stefan
97

Od kodu kompletnego

8 Programowanie obronne

8.2 Twierdzenia

Asercja to kod używany podczas programowania - zwykle procedura lub makro - który umożliwia programowi sprawdzenie samego siebie podczas działania. Kiedy twierdzenie jest prawdziwe, oznacza to, że wszystko działa zgodnie z oczekiwaniami. Jeśli jest fałszywe, oznacza to, że wykrył nieoczekiwany błąd w kodzie. Na przykład, jeśli system zakłada, że ​​zbiór informacji o klientach nigdy nie będzie zawierał więcej niż 50 000 rekordów, program może zawierać stwierdzenie, że liczba rekordów jest mniejsza lub równa 50 000. Dopóki liczba rekordów jest mniejsza lub równa 50 000, twierdzenie będzie milczące. Jeśli jednak napotka więcej niż 50 000 rekordów, głośno „stwierdzi”, że w programie jest błąd.

Asercje są szczególnie przydatne w dużych, skomplikowanych programach i programach o wysokiej niezawodności. Umożliwiają programistom szybsze usuwanie niedopasowanych założeń interfejsu, błędów, które wkradają się, gdy kod jest modyfikowany, i tak dalej.

Twierdzenie zwykle przyjmuje dwa argumenty: wyrażenie logiczne, które opisuje założenie, które ma być prawdziwe, oraz komunikat, który ma zostać wyświetlony, jeśli tak nie jest.

(…)

Zwykle nie chcesz, aby użytkownicy widzieli komunikaty potwierdzeń w kodzie produkcyjnym; asercje są używane głównie podczas opracowywania i konserwacji. Asercje są zwykle kompilowane do kodu w czasie projektowania i kompilowane poza kodem do produkcji. Podczas opracowywania asercje usuwają sprzeczne założenia, nieoczekiwane warunki, złe wartości przekazywane do rutynowych i tak dalej. Podczas produkcji są kompilowane poza kodem, aby asercje nie obniżały wydajności systemu.

juan
źródło
2
Książka „Writing Solid Code” zawiera również obszerną dyskusję na temat użycia assert. Są świetnym narzędziem do debugowania!
zooropa
39

Powinieneś go używać w sytuacjach, gdy nie chcesz, aby punkt przerwania był potrzebny w każdym małym wierszu kodu, aby sprawdzić zmienne, ale chcesz uzyskać informacje zwrotne, jeśli występują pewne sytuacje, na przykład:

Debug.Assert(someObject != null, "someObject is null! this could totally be a bug!");
thelsdj
źródło
Jeśli dodam wiersz kodu podobny do twojego powyżej, uruchomienie programu daje następujący błąd: „błąd CS0103: nazwa„ Debug ”nie istnieje w bieżącym kontekście”. Czy potrzebuję jakiegoś oświadczenia using, aby to zadziałało?
Josh Desmond
4
@JoshDesmondSystem.Diagnostics
Sinjai
16

Assert daje również kolejną okazję do chichotania z umiejętności projektowania interfejsu użytkownika firmy Microsoft. Mam na myśli: okno dialogowe z trzema przyciskami Przerwij, Ponów, Ignoruj ​​i wyjaśnienie, jak je interpretować na pasku tytułowym!

Joe
źródło
3
Przerwij / Ponów / Ignoruj ​​jest klasyczna! Czy to twierdzenia powodowały, że system Windows 3.1 wyświetlał to przez cały czas?
devlord
Zasadniczo dzieje się tak dlatego, że używa MessageBox, który, jak mówisz, pochodzi z systemu Windows 3.1 i ma tylko wstępnie zdefiniowane etykiety przycisków. Możesz więc zrozumieć, dlaczego doszło do włamania, ale nie dlaczego nadal istnieje w 2008 roku!
Joe
4
@Joe To jest coś, co powinni widzieć tylko deweloperzy, a nie użytkownicy końcowi, więc aktualizacja jest prawdopodobnie elementem o wyjątkowo niskim priorytecie. Jeśli to przeszkadza, możesz zmodyfikować kolekcje Debug.Listeners lub Trace.Listeners, aby zastąpić domyślną procedurę obsługi taką, która robi wszystko, co chcesz.
Dan Is Fiddling By Firelight
5
No cóż, teraz jest rok 2019, a to samo okno dialogowe / przyciski wciąż tu są!
Bouke
10

Assert umożliwia potwierdzenie warunku (post lub pre) w kodzie. Jest to sposób na udokumentowanie twoich zamiarów i poinformowanie debuggera za pomocą okna dialogowego, jeśli twój zamiar nie zostanie spełniony.

W przeciwieństwie do punktu przerwania, Assert idzie z twoim kodem i może służyć do dodawania dodatkowych szczegółów na temat twojego zamiaru.

Jeff Yates
źródło
10

Assert może pomóc w oddzielnym przekazywaniu komunikatów między testowaniem a wydaniem. Na przykład,

Debug.Assert(x > 2)

spowoduje przerwanie tylko w przypadku uruchamiania kompilacji „debugowania”, a nie kompilacji wydania. Jest pełen przykładem takiego zachowania tutaj

Ryan
źródło
10

Przede wszystkim Assert()metoda jest dostępna dla klas Tracei Debug.
Debug.Assert()jest wykonywany tylko w trybie debugowania.
Trace.Assert()jest wykonywany w trybie debugowania i wydania.

Oto przykład:

        int i = 1 + 3;
        // Debug.Assert method in Debug mode fails, since i == 4
        Debug.Assert(i == 3);
        Debug.WriteLine(i == 3, "i is equal to 3");

        // Trace.Assert method in Release mode is not failing.
        Trace.Assert(i == 4);
        Trace.WriteLine(i == 4, "i is equla to 4");

        Console.WriteLine("Press a key to continue...");
        Console.ReadLine();

Uruchom ten kod w trybie debugowania, a następnie w trybie wydania.

wprowadź opis obrazu tutaj

Zauważysz, że w trybie debugowania Debug.Assertinstrukcja kodu nie powiedzie się, pojawi się okno komunikatu pokazujące bieżący ślad stosu aplikacji. Nie dzieje się to w trybie wydania, ponieważ Trace.Assert()warunek jest prawdziwy (i == 4).

WriteLine() metoda po prostu zapewnia opcję rejestrowania informacji w danych wyjściowych programu Visual Studio. wprowadź opis obrazu tutaj

Serge Voloshenko
źródło
5

Twierdzenia są często widoczne w Design by Contract (DbC), które, jak rozumiem, zostały wprowadzone / zatwierdzone przez Meyer, Bertand. 1997. Konstrukcja oprogramowania zorientowanego obiektowo.

Ważną cechą jest to, że nie mogą one wywoływać skutków ubocznych, na przykład możesz obsłużyć wyjątek lub podjąć inne działanie za pomocą instrukcji if (programowanie obronne).

Asercje służą do sprawdzenia warunków przed / po kontrakcie, relacji klient / dostawca - klient musi upewnić się, że spełnione są warunki wstępne dostawcy np. wysyła 5 GBP, a dostawca musi zapewnić spełnienie warunków końcowych, np. dostarcza 12 róż. (Proste wyjaśnienie klienta / dostawcy - może przyjąć mniej i dostarczyć więcej, ale o twierdzeniach). C # wprowadza również Trace.Assert (), którego można użyć do wydania kodu.

Aby odpowiedzieć na pytanie, tak, nadal są przydatne, ale mogą zwiększyć złożoność + czytelność kodu i czas + trudne w utrzymaniu. Czy nadal powinniśmy ich używać? Tak, czy wszyscy ich użyjemy? Prawdopodobnie nie, lub nie w takim zakresie, w jakim opisuje to Meyer.

(Nawet kurs OU Java, na którym nauczyłem się tej techniki, pokazywał tylko proste przykłady, a reszta kodu nie wymuszała reguł asercji DbC w większości kodu, ale zakładano, że jest używany do zapewnienia poprawności programu!)

Knightlore
źródło
3

Sposób, w jaki o tym myślę, to Debug.Assert to sposób na ustalenie kontraktu określającego sposób wywołania metody, skupiający się na szczegółach dotyczących wartości parametru (zamiast tylko typu). Na przykład, jeśli nie masz wysyłać wartości null w drugim parametrze, dodajesz Assert wokół tego parametru, aby poinformować konsumenta, aby tego nie robił.

Zapobiega to używaniu twojego kodu w sposób bezczelny. Ale pozwala również na przejście do produkcji i nie przekazanie nieprzyjemnej wiadomości klientowi (zakładając, że zbudujesz wersję Release).

Flory
źródło
6
Należy jednak zauważyć, że nieprawidłowe parametry metod publicznych powinny generować wyjątki argumentów. Tylko metody prywatne powinny weryfikować dane wejściowe z asercjami. Wartości przychodzące z zewnątrz są zawsze podejrzane!
Jeffrey L Whitledge,