Frage

Ich habe gerade erst begonnen Skimming 'Debuggen MS .NET 2.0-Anwendungen' von John Robbins, und durch seine Evangelisation für Debug.Assert (...).

verwirrte

Er weist darauf hin, dass gut implementiert, um den Zustand Asserts speichern, etwas, von einer Fehlerbedingung, z.

Debug.Assert(i > 3, "i > 3", "This means I got a bad parameter");

Nun, persönlich, es scheint mir verrückt, dass er so liebt seinen Test Neuformulierung ohne eine tatsächliche vernünftige Kommentar ‚Business-Logik‘, vielleicht „i <= 3 darf nicht wegen des flobittyjam widgitification Prozesses passieren“.

So

, ich glaube, ich Asserts als ein Art-of low-level „Lassen Sie sich meine Annahmen schützen“ Art der Sache ..., dass man unter der Annahme, fühlt dies ist ein Test braucht man nur im Debug zu tun - das heißt, Sie schützt sie gegen Kollegen und zukünftige Programmierer, und in der Hoffnung, dass sie die Dinge tatsächlich testen.

Aber was ich nicht tue, ist zu bekommen, er geht dann weiter zu sagen, dass Sie Behauptungen zusätzlich zu dem normalen Fehlerbehandlung verwendet werden sollen; jetzt, was ich mir vorstelle ist so etwas wie folgt aus:

Debug.Assert(i > 3, "i must be greater than 3 because of the flibbity widgit status");
if (i <= 3)
{
    throw new ArgumentOutOfRangeException("i", "i must be > 3 because... i=" + i.ToString());
}

Was habe ich durch die Debug.Assert Wiederholung des Fehlerzustand Tests gewonnen? Ich glaube, ich würde es, wenn wir über Debug-only doppelte Kontrolle einer sehr wichtigen Berechnung sprechen ...

double interestAmount = loan.GetInterest();
Debug.Assert(debugInterestDoubleCheck(loan) == interestAmount, "Mismatch on interest calc");

... aber ich es nicht für Parametertests erhalten, die sicherlich einen Besuch wert sind (sowohl in der DEBUG und Releasebuilds) ... oder auch nicht. Was bin ich?

War es hilfreich?

Lösung

Assertions sind nicht für die Parameterprüfung. Parameter Prüfung sollte immer durchgeführt werden (und genau nach dem, was vorge Bedingungen festgelegt sind in der Dokumentation und / oder Spezifikation) und die ArgumentOutOfRangeException wie nötig geworfen.

Assertions sind für die Prüfung für "unmögliche" Situationen, das heißt, die Dinge, die Sie (in Ihrer Programm-Logik) übernehmen ist wahr. Die Behauptungen sind da, um Ihnen zu sagen, ob diese Annahmen aus irgendeinem Grunde gebrochen werden.

Hope, das hilft!

Andere Tipps

Es ist ein Kommunikations Aspekt vs Ausnahme werfen zu behauptet.

Lassen Sie uns sagen, dass wir eine User-Klasse mit einer Eigenschaft Name und eine ToString-Methode haben.

Wenn ToString wird wie folgt umgesetzt:

public string ToString()
{
     Debug.Assert(Name != null);
     return Name;
}

Er sagt, dass Name sollte nie null, und es ist ein Fehler in der Benutzerklasse, wenn es ist.

Wenn ToString wird wie folgt implementieren:

public string ToString()
{
     if ( Name == null )
     {
          throw new InvalidOperationException("Name is null");
     }

     return Name;
}

Er sagt, dass der Anrufer mit ToString falsch, wenn der Name null ist und sollte überprüfen, ob vor dem Aufruf.

Die Umsetzung sowohl mit

public string ToString()
{
     Debug.Assert(Name != null);
     if ( Name == null )
     {
          throw new InvalidOperationException("Name is null");
     }

     return Name;
}

sagt, wenn Name null gibt Fehler in der User-Klasse, aber wir wollen es trotzdem behandeln. (Der Benutzer muss nicht Namen überprüfen, bevor Sie anrufen.) Ich denke, das ist die Art von Sicherheit Robbins wurde zu empfehlen.

Ich habe über diese lange nachgedacht und hart, wenn es darum geht, Leitlinien für die Debug-Bereitstellung vs. behauptet in Bezug auf Tests betreffen.

Sie sollten fähig sein, Ihre Klasse mit fehlerhafter Eingabe, schlechten Zustand zu testen, ungültiger Reihenfolge der Operationen und jedem anderen denkbaren Fehlerzustand und eine Assertion sollte nie Reise. Jede Assertion prüft etwas sollte immer wahr, unabhängig von den Eingaben oder Berechnungen durchgeführt.

Gute Faustregeln Ich habe angekommen an:

  1. Asserts sind kein Ersatz für eine robusten Code, der korrekt funktioniert unabhängig von Konfiguration. Sie ergänzen.

  2. Asserts sollte nie während einer Einheit Testlauf ausgelöst werden, auch wenn sie in ungültigen Werten oder Testfehlerbedingungen Fütterung. Der Code sollte diese Bedingungen behandeln, ohne eine Assertion auftreten.

  3. Wenn eine Assertion Reisen (entweder in einem Unit-Test oder während des Tests) wird die Klasse abgehört.

Für alle anderen Fehler - in der Regel bis zu Umwelt (Netzwerkverbindung verloren) oder Missbrauch (Anrufer einen Nullwert übergeben) - es ist viel schöner und verständliches harte Kontrollen und Ausnahmen zu verwenden. Wenn eine Ausnahme auftritt, weiß der Anrufer ist es wahrscheinlich ihre Schuld. Wenn eine Assertion auftritt, weiß der Anrufer ist es wahrscheinlich ein Fehler im Code, in dem die Assertion befindet.

In Bezug auf Duplizierung: Ich bin damit einverstanden. Ich sehe nicht, warum Sie die Validierung mit einem Debug.Assert und eine Ausnahmeprüfung wiederholen würden. Nicht nur, dass es etwas Lärm, um den Code hinzuzufügen und das Wasser schlammig in Bezug auf, wer Schuld ist, aber es ist eine Form der Wiederholung.

ich ausdrücklich Kontrollen verwenden, die Ausnahmen auf öffentlich und geschützt Methoden und Behauptungen auf private Methoden werfen.

Normalerweise schützen die expliziten Kontrollen die privaten Methoden ohnehin falsche Werte zu sehen. Also wirklich, ist die Assertion für eine Bedingung überprüft, die unmöglich sein sollte. Wenn ein assert Feuer tut, es sagt mir, das es ein Defekt in der Validierungslogik in einen der öffentlichen Routinen für die Klasse enthalten ist.

Eine Ausnahme kann machen den Fehler unsichtbar Tests gefangen und geschluckt werden. Das kann nicht mit Debug.Assert passieren.

Niemand sollte jemals einen catch-Handler haben, der alle Ausnahmen abfängt, aber die Leute tun es trotzdem, und manchmal ist es unvermeidlich. Wenn Ihr Code von COM aufgerufen wird, fängt die Interop-Schicht alle Ausnahmen und verwandelt sie in Codes COM-Fehler, das heißt, Sie werden Ihre nicht behandelte Ausnahmen sehen. ASSERTS Sie nicht leiden.

Auch wenn die Ausnahme nicht behandelte sei, eine noch bessere Praxis ist ein Mini-Dump zu nehmen. Ein Bereich, wo VB ist mächtiger als C # ist, dass Sie eine Ausnahme Filter verwenden, können einen Mini-Dump zu schnappen, wenn die Ausnahme im Flug ist, und den Rest der Ausnahmebehandlung unverändert. Gregg Miskelly Blog-Post auf Ausnahmefilter inject bietet eine nützliche Art und Weise, dies zu tun von c #.

Ein weiterer Hinweis auf Vermögen ... sie inteact schlecht mit Einheit der Fehlerbedingungen in Ihrem Code zu testen. Es lohnt sich, einen Wrapper zu haben, um die Assertion für die Komponententests zu deaktivieren.

IMO ist es ein Verlust von nur Entwicklungszeit. Ordnungsgemäß umgesetzt Ausnahme gibt Ihnen ein klares Bild von dem, was passiert ist. Ich sah zu viel Anwendungen obskure zeigen "Assertion fehlgeschlagen: i <10" Fehler. Ich sehe Behauptung als eine vorübergehende Lösung. Meiner Meinung nach sollten keine Behauptungen in einer endgültigen Version eines Programms sein. In meiner Praxis habe ich Behauptungen für schnelle und schmutzige Kontrollen. Endfassung des Codes sollte fehlerhafte Situation berücksichtigen und sich entsprechend verhalten. Wenn etwas Schlimmes passiert, haben Sie zwei Möglichkeiten: behandeln oder stirb. Funktion sollte eine Ausnahme mit aussagekräftiger Beschreibung werfen, wenn falsche Parameter übergeben. Ich habe keine Punkte in Doppelvalidierungslogik zu sehen.

Beispiel für eine gute Verwendung von Assert:

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

Ich persönlich denke, dass Assert sollte nur verwendet werden, wenn Sie wissen, was außerhalb ist wünschenswert Grenzen, aber Sie können sicher sein, es einigermaßen sicher ist, fortzusetzen. In allen anderen Fällen (fühlen Umständen frei Punkt aus haben gedacht ich nicht) verwenden Ausnahmen hart und schnell zum Scheitern verurteilt.

Der Schlüssel Kompromiss für mich ist, ob Sie eine Live / Produktionssystem mit einer Ausnahme zu Fall bringen wollen Korruption zu vermeiden und erleichtern die Fehlersuche, oder ob Sie haben eine Situation auftreten, die nie unbemerkt erlaubt sein sollte, in Test / debug, um fortzufahren Versionen aber erlaubt sein könnte in der Produktion (Anmeldung eine Warnung natürlich).

, um fortzufahren

cf. http://c2.com/cgi/wiki?FailFast kopiert und von Java-Frage geändert: Ausnahme Vs Assertion

Hier ist um 2 Cent.

Ich denke, dass der beste Weg, um beiden Behauptungen und Ausnahmen zu verwenden ist. Die Hauptunterschiede zwischen den beiden Verfahren, imho, falls die Assert-Anweisungen können leicht aus dem Anmeldungstext (definiert, bedingten Attribute ...) entfernt werden, während Exception geworfen abhängig (tipically) durch einen bedingten Code, der schwerer zu entfernen ist ( multine Abschnitt mit Präprozessor conditionals).

Jede Anwendung Ausnahme richtig gehandhabt werden soll, während Aussagen gelten nur während der Algorithmus Entwicklung und Prüfung erfüllt werden.

Wenn Sie eine Null-Objekt Referenz als Routine-Parameter übergeben, und verwenden Sie diesen Wert, erhalten Sie eine Null-Zeiger-Ausnahme. In der Tat: Warum sollten Sie eine Assertion schreiben? Es ist eine Verschwendung von Zeit in diesem Fall. Aber was private Klasse Mitglieder in Klasse Routinen verwendet? Wenn diese Werte irgendwo festgelegt sind, ist besser mit einer Behauptung zu überprüfen, ob ein Nullwert festgelegt ist. Das ist nur, weil, wenn Sie das Element zu verwenden, können Sie eine Null-Zeiger-Ausnahme erhalten, aber Sie wissen nicht, wie der Wert festgelegt wurde. Diese verursachen einen Neustart des Programms bricht auf alle Gebrauch Eintrittspunkt das private Mitglied zu setzen.

Ausnahme ist nützlich, aber sie können (imho) sehr schwer zu handhaben und es besteht die Möglichkeit, zu viele Ausnahmen zu verwenden. Und sie erfordert zusätzliche Prüfung, vielleicht unerwünscht, den Code zu optimieren. Ich persönlich verwende Ausnahmen nur, wenn der Code eine tiefe Fangkontrolle erfordert (Fangmeldungen sind sehr niedrig in dem Call-Stack) oder wenn die Funktionsparameter sind nicht im Code fest einprogrammiert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top