Unter comp.lang.c ++ wird eine Diskussion darüber geführt, ob Zusicherungen, die in C ++ standardmäßig nur in Debug-Builds vorhanden sind, im Produktionscode beibehalten werden sollen oder nicht.
Natürlich ist jedes Projekt einzigartig, daher ist meine Frage hier nicht so sehr, ob Aussagen beibehalten werden sollten, aber in welchen Fällen ist dies empfehlenswert / keine gute Idee.
Mit Behauptung meine ich:
- Eine Laufzeitprüfung, die einen Zustand testet, der, wenn er falsch ist, einen Fehler in der Software aufdeckt.
- Ein Mechanismus, durch den das Programm angehalten wird (möglicherweise nach wirklich minimalen Aufräumarbeiten).
Ich spreche nicht unbedingt über C oder C ++.
Meine eigene Meinung ist, dass Sie, wenn Sie der Programmierer sind, aber die Daten nicht besitzen (was bei den meisten kommerziellen Desktop-Anwendungen der Fall ist), diese beibehalten sollten, da eine fehlerhafte Bestätigung einen Fehler anzeigt und Sie nicht gehen sollten mit einem Fehler, mit dem Risiko, die Daten des Benutzers zu beschädigen. Dies zwingt Sie dazu, vor dem Versand stark zu testen, und macht Fehler besser sichtbar, sodass Sie sie leichter erkennen und beheben können.
Was ist deine Meinung / Erfahrung?
Prost,
Carl
Siehe verwandte Frage hier
Antworten und Updates
Hey Graham,
Eine Behauptung ist schlicht und einfach ein Fehler und sollte daher wie eine behandelt werden. Da ein Fehler im Release-Modus behandelt werden soll, brauchen Sie keine Assertions.
Deshalb bevorzuge ich das Wort "Bug", wenn ich über Behauptungen spreche. Es macht die Dinge viel klarer. Für mich ist das Wort "Fehler" zu vage. Eine fehlende Datei ist ein Fehler, kein Fehler, und das Programm sollte sich damit befassen. Der Versuch, einen Nullzeiger zu dereferenzieren, ist ein Fehler, und das Programm sollte anerkennen, dass etwas nach schlechtem Käse riecht.
Daher sollten Sie den Zeiger mit einer Zusicherung testen, aber das Vorhandensein der Datei mit normalem Fehlerbehandlungscode.
Etwas abseits des Themas, aber ein wichtiger Punkt in der Diskussion.
Wenn Ihre Behauptungen als Heads-up in den Debugger einbrechen, wenn sie fehlschlagen, warum nicht? Es gibt jedoch viele Gründe, warum eine Datei nicht existieren könnte, die völlig außerhalb der Kontrolle Ihres Codes liegen: Lese- / Schreibrechte, volle Festplatte, nicht angeschlossenes USB-Gerät usw. Da Sie keine Kontrolle darüber haben, sind dies meines Erachtens Behauptungen nicht der richtige Weg, um damit umzugehen.
Carl
Thomas,
Ja, ich habe Code Complete und muss sagen, dass ich diesem speziellen Rat überhaupt nicht zustimme.
Angenommen, Ihr benutzerdefinierter Speicherzuweiser ist fehlerhaft und setzt einen Speicherblock auf Null, der noch von einem anderen Objekt verwendet wird. Ich habe zufällig einen Zeiger auf Null gesetzt, den dieses Objekt regelmäßig dereferenziert, und eine der Invarianten ist, dass dieser Zeiger niemals Null ist, und Sie haben einige Aussagen, um sicherzustellen, dass dies auch so bleibt. Was machen Sie, wenn der Zeiger plötzlich null ist? Sie nur wenn () um, in der Hoffnung, dass es funktioniert?
Denken Sie daran, wir sprechen hier über Produktcode, sodass Sie nicht in den Debugger eindringen und den lokalen Status überprüfen müssen. Dies ist ein echter Fehler auf dem Computer des Benutzers.
Carl
Antworten:
Behauptungen sind Kommentare, die nicht veraltet sind. Sie dokumentieren, welche theoretischen Zustände beabsichtigt sind und welche Zustände nicht auftreten sollten. Wenn der Code geändert wird, damit die Status geändert werden können, wird der Entwickler bald informiert und muss die Zusicherung aktualisieren.
quelle
Gestatten Sie mir, Steve McConnells Code Complete zu zitieren. Der Abschnitt über Behauptungen ist 8.2.
Später im selben Abschnitt wird dieser Rat gegeben:
Ich denke, solange die Leistung kein Problem darstellt, lassen Sie die Behauptung in, aber anstatt eine Nachricht anzuzeigen, lassen Sie sie in eine Protokolldatei schreiben. Ich denke, dass der Rat auch in Code Complete enthalten ist, aber ich finde ihn momentan nicht.
quelle
Lassen Sie Zusicherungen im Produktionscode aktiviert, es sei denn, Sie haben gemessen, dass das Programm bei deaktiviertem Programm erheblich schneller ausgeführt wird.
http://c2.com/cgi/wiki?ShipWithAssertionsOn
quelle
assert ref != null;
ist anders alsif (ref == null) throw new IllegalArgumentException();
Sie sollten die erste nicht für Voraussetzungen verwenden, die falsch sein könnten. Sie müssenassert
für Dinge verwenden, die nicht falsch sein können. Beispiel,int i = -1 * someNumber; i = i * i;
dann später, um die Leute daran zu erinnern, dassi
positiv ist,assert i > 0;
Wenn Sie sogar daran denken, Behauptungen in der Produktion zu belassen, denken Sie wahrscheinlich falsch darüber nach. Der springende Punkt bei Behauptungen ist, dass Sie sie in der Produktion ausschalten können, da sie nicht Teil Ihrer Lösung sind. Sie sind ein Entwicklungswerkzeug, mit dem überprüft wird, ob Ihre Annahmen korrekt sind. Aber wenn Sie in Produktion gehen, sollten Sie bereits Vertrauen in Ihre Annahmen haben.
Es gibt jedoch einen Fall, in dem ich Behauptungen in der Produktion aktivieren werde: Wenn wir in der Produktion auf einen reproduzierbaren Fehler stoßen, den wir in einer Testumgebung nur schwer reproduzieren können, kann es hilfreich sein, den Fehler mit aktivierten Behauptungen zu reproduzieren in der Produktion, um zu sehen, ob sie nützliche Informationen liefern.
Eine interessantere Frage lautet: Wann schalten Sie in Ihrer Testphase die Behauptungen aus?
quelle
Behauptungen sollten niemals im Produktionscode bleiben. Wenn eine bestimmte Behauptung im Produktionscode nützlich zu sein scheint, sollte sie keine Behauptung sein. Es sollte eine Laufzeitfehlerprüfung sein, dh etwas, das wie folgt codiert ist :
if( condition != expected ) throw exception
.Der Begriff "Behauptung" bedeutet "eine Prüfung nur für die Entwicklungszeit, die nicht auf dem Feld durchgeführt wird".
Wenn Sie anfangen zu denken, dass Behauptungen es auf das Feld schaffen könnten, werden Sie unweigerlich auch andere gefährliche Gedanken machen, wie sich zu fragen, ob eine bestimmte Behauptung es wirklich wert ist, gemacht zu werden. Es gibt keine Behauptung, die es nicht wert ist, gemacht zu werden. Sie sollten sich niemals fragen: "Soll ich das behaupten oder nicht?" Sie sollten sich nur fragen: "Gibt es etwas, das ich vergessen habe zu behaupten?"
quelle
Sofern die Profilerstellung nicht zeigt, dass die Behauptungen Leistungsprobleme verursachen, sollten sie auch in der Produktionsversion verbleiben.
Ich denke jedoch, dass dies auch erfordert, dass Sie Assertionsfehler etwas elegant behandeln. Beispielsweise sollten sie zu einem allgemeinen Dialog führen, mit der Option, das Problem (automatisch) den Entwicklern zu melden und nicht nur das Programm zu beenden oder zum Absturz zu bringen. Sie sollten auch darauf achten, keine Behauptungen für Bedingungen zu verwenden, die Sie tatsächlich zulassen, aber möglicherweise nicht mögen oder als unerwünscht betrachten. Diese Bedingungen sollten von anderen Teilen des Codes behandelt werden.
quelle
In meinem C ++ definiere ich REQUIRE (x), das assert (x) ähnelt, außer dass es eine Ausnahme auslöst, wenn die Assertion in einem Release-Build fehlschlägt.
Da eine fehlgeschlagene Behauptung auf einen Fehler hinweist, sollte dieser auch in einem Release-Build ernsthaft behandelt werden. Wenn die Leistung meines Codes wichtig ist, verwende ich häufig REQUIRE () für Code höherer Ebene und assert () für Code niedrigerer Ebene, der schnell ausgeführt werden muss. Ich verwende auch REQUIRE, anstatt zu behaupten, ob die Fehlerbedingung durch Daten verursacht werden kann, die aus von einem Dritten geschriebenem Code oder durch Dateibeschädigung übergeben wurden (optimalerweise würde ich den Code speziell so gestalten, dass er sich im Falle einer Dateibeschädigung gut verhält, aber wir habe nicht immer Zeit dafür.)
Sie sagen, Sie sollten diese Assert-Nachrichten nicht den Endbenutzern anzeigen, weil sie sie nicht verstehen. So? Endbenutzer senden Ihnen möglicherweise eine E-Mail mit einem Screenshot oder einem Text der Fehlermeldung, der Ihnen beim Debuggen hilft. Wenn der Benutzer einfach "es ist abgestürzt" sagt, können Sie das Problem weniger beheben. Es ist besser, die Assertion-Failure-Nachrichten automatisch über das Internet an sich selbst zu senden. Dies funktioniert jedoch nur, wenn der Benutzer über einen Internetzugang verfügt und Sie dessen Erlaubnis erhalten können.
quelle
Wenn Sie sie behalten möchten, ersetzen Sie sie durch Fehlerbehandlung. Nichts schlimmeres als ein Programm, das einfach verschwindet. Ich sehe nichts Falsches daran, bestimmte Fehler als schwerwiegende Fehler zu behandeln, aber sie sollten an einen Abschnitt Ihres Programms weitergeleitet werden, der dafür gerüstet ist, Daten zu sammeln, zu protokollieren und den Benutzer darüber zu informieren, dass Ihre App einen unerwünschten Zustand aufweist ist aufregend.
quelle
Vorausgesetzt, sie werden wie jeder andere Fehler behandelt, sehe ich kein Problem damit. Beachten Sie jedoch, dass fehlgeschlagene Zusicherungen in C wie in anderen Sprachen das Programm nur beenden und dies für Produktionssysteme normalerweise nicht ausreicht.
Es gibt einige Ausnahmen: Mit PHP können Sie beispielsweise einen benutzerdefinierten Handler für Assertionsfehler erstellen, damit Sie benutzerdefinierte Fehler anzeigen, detaillierte Protokolle erstellen usw. können, anstatt nur zu beenden.
quelle
Unsere Datenbankserversoftware enthält sowohl Produktions- als auch Debug-Zusicherungen. Debug-Zusicherungen sind genau das - sie werden im Produktionscode entfernt. Produktionsbehauptungen treten nur auf, wenn (a) ein Zustand vorliegt, der niemals existieren sollte , und (b) es nicht möglich ist, diesen Zustand zuverlässig wiederherzustellen. Eine Produktionszusicherung zeigt an, dass ein Fehler in der Software aufgetreten ist oder eine Art Datenbeschädigung aufgetreten ist.
Da es sich um ein Datenbanksystem handelt und wir potenziell unternehmenskritische Daten speichern, tun wir alles, um beschädigte Daten zu vermeiden. Wenn eine Bedingung vorliegt, die dazu führen kann, dass wir falsche Daten speichern, bestätigen wir sofort, setzen alle Transaktionen zurück und stoppen den Server.
Wir versuchen jedoch auch, Produktionsaussagen in leistungskritischen Routinen zu vermeiden.
quelle
Ich sehe Behauptungen als Inline-Unit-Tests. Nützlich für einen schnellen Test während der Entwicklung, aber letztendlich sollten diese Behauptungen überarbeitet werden, um in Unit-Tests extern getestet zu werden.
quelle
Ich finde es am besten, alle Fehler zu behandeln, die im Umfang liegen, und Aussagen für Annahmen zu verwenden, von denen wir behaupten, dass sie wahr sind.
Wenn Ihr Programm eine Datei öffnet / liest / schließt, ist es nicht möglich, die Datei nicht öffnen zu können. Dies ist eine echte Möglichkeit, die mit anderen Worten fahrlässig ignoriert werden könnte. Dem sollte also ein Fehlerprüfcode zugeordnet sein.
Nehmen wir jedoch an, dass fopen () so dokumentiert ist, dass es immer ein gültiges, offenes Dateihandle zurückgibt. Sie öffnen die Datei und übergeben sie an Ihre Funktion readfile ().
Diese Readfile-Funktion kann in diesem Zusammenhang und wahrscheinlich gemäß ihrer Designspezifikation ziemlich genau davon ausgehen, dass sie eine gültige Datei ptr erhalten wird. Es wäre also verschwenderisch, in einem so einfachen Programm Fehlerbehandlungscode für den negativen Fall hinzuzufügen. Es sollte jedoch zumindest die Annahme dokumentieren, dass dies tatsächlich der Fall ist, bevor die Ausführung fortgesetzt wird. Es sollte nicht WIRKLICH davon ausgegangen werden, dass dies immer gültig ist, falls es falsch aufgerufen oder beispielsweise in ein anderes Programm kopiert / eingefügt wird.
Also, readfile () {assert (fptr! = NULL); ..} ist in diesem Fall angemessen, während dies bei einer vollständigen Fehlerbehandlung nicht der Fall ist (das Ignorieren der Tatsache, dass das tatsächliche Lesen der Datei ohnehin ein Fehlerbehandlungssystem erfordern würde).
Und ja, diese Behauptungen sollten im Produktionscode bleiben, es sei denn, es ist absolut notwendig, sie zu deaktivieren. Selbst dann sollten Sie sie wahrscheinlich nur in leistungskritischen Abschnitten deaktivieren.
quelle
Angenommen, ein Code befindet sich in der Produktion und trifft auf eine Behauptung, die normalerweise ausgelöst wird. Die Behauptung hat einen Fehler gefunden! Außer es hat nicht, weil die Behauptung ausgeschaltet ist.
Also was passiert jetzt? Entweder stürzt das Programm (1) an einem weiter von der Ursache des Problems entfernten Punkt auf nicht informative Weise ab oder (2) läuft fröhlich bis zum Abschluss, was wahrscheinlich zu einem falschen Ergebnis führt.
Keines der beiden Szenarien ist einladend. Lassen Sie Behauptungen auch in der Produktion aktiv.
quelle
Ich verwende Assertions selten für andere Zwecke als die Überprüfung des Kompilierzeittyps. Ich würde eine Ausnahme anstelle einer Behauptung verwenden, nur weil die meisten Sprachen dafür ausgelegt sind.
Ich biete ein Beispiel
gegen
Wie würde die Anwendung mit der Behauptung umgehen? Ich bevorzuge die alte
try catch
Methode, mit schwerwiegenden Fehlern umzugehen.quelle
Die meiste Zeit, wenn ich Assertion in Java (das Assert-Schlüsselwort) verwende, füge ich danach automatisch einige Produktionscodes hinzu. Je nach Fall kann es sich um eine Protokollierungsnachricht, eine Ausnahme oder nichts handeln.
Meiner Meinung nach sind alle Ihre Behauptungen in der Entwicklungsversion von entscheidender Bedeutung, nicht in der Produktionsfreigabe. Einige von ihnen müssen aufbewahrt werden, andere müssen verworfen werden.
quelle
Behauptungen sind keine Fehler und sollten nicht als Fehler behandelt werden. Wenn eine Zusicherung ausgelöst wird, bedeutet dies, dass Ihr Code oder alternativ der Code, der Ihren Code aufruft, einen Fehler enthält.
Es gibt einige Punkte, um das Aktivieren von Zusicherungen im Produktionscode zu vermeiden: 1. Sie möchten nicht, dass Ihrem Endbenutzer eine Meldung wie "ASSERTION failed MyPrivateClass.cpp Zeile 147" angezeigt wird. Der Endbenutzer ist NICHT Ihr QS-Ingenieur. 2. ASSERTION könnte Leistung beeinflussen
Es gibt jedoch einen starken Grund, Aussagen zu hinterlassen: ASSERTION kann die Leistung und das Timing beeinflussen, und leider ist dies manchmal wichtig (insbesondere in eingebetteten Systemen).
Ich neige dazu, dafür zu stimmen, dass die Behauptung im Produktionscode aktiviert bleibt, aber ich stelle sicher, dass diese Ausdrucke nicht dem Endbenutzer zugänglich sind.
~ Yitzik
quelle
Eine Behauptung ist schlicht und einfach ein Fehler und sollte daher wie eine behandelt werden.
Da ein Fehler im Release-Modus behandelt werden soll, brauchen Sie keine Assertions.
Der Hauptvorteil, den ich für Behauptungen sehe, ist eine bedingte Unterbrechung - sie sind viel einfacher einzurichten, als durch die Fenster von VC zu bohren, um etwas einzurichten, das 1 Codezeile benötigt.
quelle