Das Standardverhalten assert
in C ++ besteht darin, in Release-Builds nichts zu tun. Ich gehe davon aus, dass dies aus Gründen der Leistung und möglicherweise um zu verhindern, dass Benutzer unangenehme Fehlermeldungen sehen.
Ich würde jedoch argumentieren, dass die Situationen, in denen eine assert
ausgelöst hätte, aber deaktiviert war, noch problematischer sind, da die Anwendung dann wahrscheinlich noch schlimmer abstürzt, da eine Invariante defekt ist.
Außerdem zählt das Leistungsargument für mich nur, wenn es sich um ein messbares Problem handelt. Die meisten assert
s in meinem Code sind nicht viel komplexer als
assert(ptr != nullptr);
Dies hat nur geringe Auswirkungen auf den meisten Code.
Dies führt mich zu der Frage: Sollten Assertions (dh das Konzept, nicht die spezifische Implementierung) in Release-Builds aktiv sein? Warum nicht)?
Bitte beachten Sie, dass es bei dieser Frage nicht darum geht, wie Sie Asserts in Release-Builds aktivieren (wie #undef _NDEBUG
oder mithilfe einer selbst definierten Assert-Implementierung). Darüber hinaus geht es nicht darum, Asserts in Drittanbieter- / Standardbibliothekscode zu aktivieren, sondern in von mir gesteuertem Code.
quelle
Antworten:
Der Klassiker
assert
ist ein Tool aus der alten Standard-C-Bibliothek, nicht aus C ++. Zumindest aus Gründen der Abwärtskompatibilität ist es weiterhin in C ++ verfügbar.Ich habe keine genaue Zeitleiste der C-Standard-Bibliotheken zur Hand, aber ich bin mir ziemlich sicher, dass
assert
sie kurz nach dem Start von K & R C (um 1978) verfügbar waren. In klassischem C muss zum Schreiben robuster Programme das Hinzufügen von NULL-Zeigertests und die Überprüfung der Array-Grenzen viel häufiger durchgeführt werden als in C ++. Das Brutto von NULL-Zeigertests kann vermieden werden, indem Referenzen und / oder intelligente Zeiger anstelle von Zeigern verwendet werden, und indem diestd::vector
Überprüfung der Array-Grenzen häufig nicht erforderlich ist. Darüber hinaus war der Performance-Hit von 1980 definitiv viel wichtiger als heute. Ich denke, das ist sehr wahrscheinlich der Grund, warum "assert" standardmäßig nur für Debug-Builds aktiviert wurde.Darüber hinaus ist für eine echte Fehlerbehandlung im Produktionscode eine Funktion, die nur eine Bedingung oder Invariante testet und das Programm abstürzt, wenn die Bedingung nicht erfüllt ist, in den meisten Fällen nicht flexibel genug. Für das Debuggen ist das wahrscheinlich in Ordnung, da derjenige, der das Programm ausführt und den Fehler beobachtet, normalerweise einen Debugger zur Hand hat, um zu analysieren, was passiert. Für den Seriencode muss eine sinnvolle Lösung jedoch eine Funktion oder ein Mechanismus sein, der
testet eine Bedingung (und stoppt die Ausführung in dem Bereich, in dem die Bedingung fehlschlägt)
Gibt eine eindeutige Fehlermeldung aus, falls die Bedingung nicht erfüllt ist
Ermöglicht dem äußeren Bereich, die Fehlermeldung aufzunehmen und an einen bestimmten Kommunikationskanal auszugeben. Dieser Kanal kann so etwas wie stderr, eine Standardprotokolldatei, ein Meldungsfeld in einem GUI-Programm, ein allgemeiner Rückruf zur Fehlerbehandlung, ein netzwerkfähiger Fehlerkanal oder etwas sein, das am besten zu der jeweiligen Software passt.
Hiermit kann der äußere Bereich auf Einzelfallbasis entscheiden, ob das Programm ordnungsgemäß beendet oder fortgesetzt werden soll.
(Natürlich gibt es auch Situationen, in denen das sofortige Beenden des Programms im Falle einer nicht erfüllten Bedingung die einzig sinnvolle Option ist. In solchen Fällen sollte dies jedoch auch in einem Release-Build und nicht nur in einem Debug-Build geschehen.)
Da der Klassiker
assert
diese Funktionen nicht bietet, eignet er sich nicht für einen Release-Build, vorausgesetzt, der Release-Build wird in der Produktion bereitgestellt.Jetzt können Sie fragen, warum es in der C-Standardbibliothek keine solche Funktion oder keinen solchen Mechanismus gibt, der diese Art von Flexibilität bietet. Tatsächlich gibt es in C ++ einen Standardmechanismus mit all diesen (und weiteren) Funktionen, und Sie wissen, dass dies Ausnahmen genannt werden .
In C ist es jedoch schwierig, einen guten Allzweck-Standardmechanismus für die Fehlerbehandlung mit allen genannten Funktionen zu implementieren, da es keine Ausnahmen als Teil der Programmiersprache gibt. Daher haben die meisten C-Programme ihre eigenen Fehlerbehandlungsmechanismen mit Rückkehrcodes oder "goto" s oder "long jumps" oder einer Mischung daraus. Dies sind oft pragmatische Lösungen, die für die jeweilige Art von Programm geeignet sind, aber nicht "allgemein genug" sind, um in die C-Standardbibliothek zu passen.
quelle
#include <cassert>
. Das macht jetzt total Sinn.assert
ist auch das falsche Tool (das Auslösen einer Ausnahme kann in der Tat auch die falsche Reaktion sein) ). Ich bin mir jedoch ziemlich sicher, dass in der Realitätassert
auch viele Tests in C durchgeführt wurden, bei denen in C ++ heutzutage Ausnahmen verwendet wurden.Wenn Sie wünschen, dass in einer Version Asserts aktiviert wurden, haben Sie Asserts aufgefordert, den falschen Job auszuführen.
Der Sinn von Behauptungen ist, dass sie in einer Version nicht aktiviert sind. Dies ermöglicht das Testen von Invarianten während der Entwicklung mit Code, der sonst Gerüstcode sein müsste. Code, der vor der Veröffentlichung entfernt werden muss.
Wenn Sie etwas haben, von dem Sie glauben, dass es auch während der Veröffentlichung getestet werden sollte, schreiben Sie Code, der es testet. Das
If throw
Konstrukt funktioniert sehr gut. Wenn Sie etwas anderes sagen möchten als die anderen Würfe, verwenden Sie einfach eine beschreibende Ausnahme, die sagt, was Sie sagen möchten.Es ist nicht so, dass Sie nicht ändern können, wie Sie Behauptungen verwenden. Wenn Sie dies tun, erhalten Sie nichts Nützliches, es läuft den Erwartungen zuwider und es bleibt Ihnen keine saubere Möglichkeit, das zu tun, was Behauptungen tun sollten. Fügen Sie Tests hinzu, die in einer Version inaktiv sind.
Warum kein relase_assert? Ehrlich gesagt, weil Asserts für die Produktion nicht gut genug sind. Ja, es gibt ein Bedürfnis, aber nichts erfüllt dieses Bedürfnis. Oh sicher, Sie können Ihre eigenen entwerfen. Mechanisch benötigt Ihre throwIf- Funktion nur einen Bool und eine Ausnahme zum Werfen. Und das passt vielleicht zu Ihren Bedürfnissen. Aber Sie schränken das Design wirklich ein. Deshalb wundert es mich nicht, dass es in Ihrer Sprachbibliothek kein integriertes System zum Werfen von Ausnahmen gibt. Es ist sicher nicht so, dass du es nicht kannst. Andere haben . Aber der Fall, dass etwas schief geht, macht für die meisten Programme 80% der Arbeit aus. Und bisher hat uns noch niemand eine gute Einheitsgröße gezeigt. Der effektive Umgang mit diesen Fällen kann kompliziert werden. Wenn wir ein Release_assert-System in Dosen gehabt hätten, das unseren Anforderungen nicht entsprochen hätte, hätte es mehr Schaden als Nutzen gebracht. Sie fragen nach einer guten Abstraktion, die bedeutet, dass Sie nicht über dieses Problem nachdenken müssen. Ich möchte auch eine, aber es sieht nicht so aus, als wären wir schon da.
Warum sind Asserts in der Version deaktiviert? Asserts wurden auf der Höhe des Alters des Gerüstcodes erstellt. Code, den wir entfernen mussten, weil wir wussten, dass wir ihn nicht in der Produktion haben wollten, aber wussten, dass wir in der Entwicklung laufen wollten, um Fehler zu finden. Asserts waren eine sauberere Alternative zu dem
if (DEBUG)
Muster, bei dem wir den Code belassen , ihn aber deaktivieren konnten. Dies geschah, bevor Unit-Tests als Hauptmethode zur Trennung von Testcode und Produktionscode eingesetzt wurden. Asserts werden auch heute noch von erfahrenen Unit-Testern verwendet, um die Erwartungen zu verdeutlichen und um Fälle abzudecken, in denen sie immer noch besser abschneiden als Unit-Tests.Warum nicht einfach den Debugging-Code in der Produktion belassen? Da der Produktionscode das Unternehmen nicht in Verlegenheit bringen, die Festplatte nicht formatieren, die Datenbank nicht beschädigen und dem Präsidenten keine drohenden E-Mails senden darf. Kurz gesagt, es ist schön, Debugging-Code an einem sicheren Ort schreiben zu können, an dem Sie sich darüber keine Gedanken machen müssen.
quelle
catch(...)
ist.if (DEBUG)
etwas anderes als das Debuggen von Code steuern. Die Mikrooptimierung kann in Ihrem Fall nichts bedeuten. Aber die Redewendung sollte nicht unterlaufen werden, nur weil Sie sie nicht brauchen.assert
sondern vom Konzept einer Behauptung. Ich möchteassert
die Leser nicht missbrauchen oder verwirren. Ich wollte fragen, warum das überhaupt so ist. Warum gibt es keine zusätzlichenrelease_assert
? Gibt es keine Notwendigkeit dafür? Was ist der Grund für die Behauptung, dass die Freigabe deaktiviert ist?You're asking for a good abstraction.
Ich bin mir darüber nicht sicher. Ich möchte mich hauptsächlich mit Problemen befassen, bei denen es keine Wiederherstellung gibt und die niemals auftreten sollten. Nehmen Sie dies zusammen mitBecause production code needs to [...] not format the hard drive [...]
und ich würde sagen, für Fälle, in denen Invarianten gebrochen sind, würde ich jederzeit eine Freigabe über UB annehmen.Behauptungen sind ein Debugging-Tool , keine defensive Programmiertechnik. Wenn Sie die Validierung unter allen Umständen durchführen möchten, führen Sie die Validierung durch, indem Sie eine Bedingung schreiben - oder erstellen Sie ein eigenes Makro, um die Boilerplate zu verkleinern.
quelle
assert
ist eine Form der Dokumentation, wie Kommentare. Wie Kommentare würden Sie sie normalerweise nicht an Kunden versenden - sie gehören nicht in den Versionscode.Das Problem bei Kommentaren ist jedoch, dass sie veraltet sein können und dennoch unverändert bleiben. Aus diesem Grund sind Asserts gut - sie werden im Debug-Modus überprüft. Wenn die Zusicherung veraltet ist, stellen Sie sie schnell fest und wissen immer noch, wie die Zusicherung behoben werden kann. Dieser Kommentar, der vor 3 Jahren veraltet war? Irgendjemand schätzt.
quelle
Wenn Sie nicht möchten, dass eine "Zusicherung" deaktiviert wird, können Sie eine einfache Funktion schreiben, die einen ähnlichen Effekt hat:
Das heißt,
assert
ist für Tests , bei denen Sie tun wollen , dass sie in dem mitgelieferten Produkt gehen weg. Wenn Sie möchten, dass dieser Test Teil des definierten Verhaltens des Programms ist,assert
ist das das falsche Werkzeug.quelle
Es ist sinnlos zu diskutieren, was behauptet werden soll, was getan wird. Wenn Sie etwas anderes wollen, schreiben Sie Ihre eigene Funktion. Ich habe zum Beispiel Assert, der im Debugger stoppt oder nichts tut. Ich habe AssertFatal, das die App zum Absturz bringt. Ich habe die Bool-Funktionen Asserted und AssertionFailed, die das Ergebnis bestätigen und zurückgeben, damit ich die Situation sowohl bestätigen als auch behandeln kann.
Bei unerwarteten Problemen müssen Sie entscheiden, wie Entwickler und Benutzer am besten damit umgehen können.
quelle
verify(cond)
der normale Weg, das Ergebnis durchzusetzen und zurückzugeben?Wie andere betonten,
assert
ist es eine Art letzte Bastion der Verteidigung gegen Programmiererfehler, die niemals passieren sollten. Es handelt sich um Plausibilitätsprüfungen, die hoffentlich zum Zeitpunkt Ihres Versands nicht von links nach rechts scheitern sollten.Es wurde auch so konzipiert , dass es in stabilen Release-Builds nicht verwendet wird, aus welchen Gründen auch immer die Entwickler dies für nützlich halten: Ästhetik, Leistung, was immer sie wollen. Es ist Teil dessen, was einen Debugbuild von einem Releasebuild trennt, und per Definition enthält ein Releasebuild keine derartigen Aussagen. Es gibt also eine Subversion des Designs, wenn Sie den analogen "Release-Build mit vorhandenen Zusicherungen" freigeben möchten , bei dem es sich um einen Versuch handelt, ein Release mit einer
_DEBUG
Präprozessordefinition und keinerNDEBUG
Definition zu erstellen . Es ist nicht mehr wirklich ein Release Build.Das Design erstreckt sich sogar bis in die Standardbibliothek. Als sehr einfaches Beispiel unter vielen, viele Implementierungen
std::vector::operator[]
wirdassert
eine Plausibilitätsprüfung , um sicherzustellen , überprüfen Sie nicht mit dem Vektor außerhalb der Grenzen. Und die Standardbibliothek wird deutlich schlechter, wenn Sie solche Prüfungen in einem Release-Build aktivieren. Ein Maßstab für dievector
Verwendungoperator[]
und ein Füllcode mit solchen Zusicherungen, die für ein einfaches altes dynamisches Array enthalten sind, zeigt häufig, dass das dynamische Array erheblich schneller ist, bis Sie solche Überprüfungen deaktivieren, sodass sie sich häufig auf die Leistung auswirken. Eine Nullzeigerprüfung hier und eine Prüfung außerhalb der Grenzen dort kann tatsächlich einen enormen Aufwand bedeuten, wenn solche Prüfungen millionenfach auf jeden Frame in kritischen Schleifen angewendet werden, die dem Code so einfach wie das Dereferenzieren eines intelligenten Zeigers oder das Zugreifen auf ein Array vorangehen.Sie wünschen sich daher höchstwahrscheinlich ein anderes Tool für den Job und eines, das nicht für Release-Builds vorgesehen ist, wenn Sie Release-Builds wünschen, die solche Überprüfungen in Schlüsselbereichen durchführen. Das nützlichste, was ich persönlich finde, ist die Protokollierung. Wenn ein Benutzer in diesem Fall einen Fehler meldet, wird es viel einfacher, wenn er ein Protokoll anfügt und die letzte Zeile des Protokolls einen großen Hinweis darauf gibt, wo der Fehler aufgetreten ist und was er sein könnte. Wenn ich dann ihre Schritte in einem Debugbuild wiedergebe, erhalte ich möglicherweise ebenfalls einen Assertionsfehler, und dieser Assertionsfehler gibt mir weitere wichtige Hinweise, um meine Zeit zu optimieren. Da die Protokollierung jedoch relativ teuer ist, verwende ich sie nicht, um äußerst einfache Sicherheitsüberprüfungen durchzuführen, z. B. um sicherzustellen, dass in einer generischen Datenstruktur nicht außerhalb der Grenzen auf ein Array zugegriffen wird.
Schließlich, und einigermaßen in Übereinstimmung mit Ihnen, könnte ein vernünftiger Fall eintreten, in dem Sie Testern tatsächlich etwas übergeben möchten, das einem Debugbuild beim Alphatesten ähnelt, beispielsweise mit einer kleinen Gruppe von Alphatestern, die beispielsweise einen NDA unterzeichnet haben . Dort wird der Alphatest möglicherweise optimiert, wenn Sie Ihren Testern nicht nur einen vollständigen Release-Build mit Debugging-Informationen übergeben, sondern auch einige Debug- / Entwicklungsfunktionen wie Tests, die sie ausführen können, und ausführlichere Ausgaben, während sie die Software ausführen. Ich habe zumindest einige große Spielefirmen gesehen, die so etwas für Alpha gemacht haben. Aber das ist für so etwas wie Alpha oder interne Tests, bei denen Sie wirklich versuchen, den Testern etwas anderes als einen Release-Build zu geben. Wenn Sie tatsächlich versuchen, einen Release-Build zu versenden, sollte dies per Definition nicht der Fall sein
_DEBUG
definiert oder das ist wirklich verwirrend den Unterschied zwischen einem "Debug" und "Release" Build.Wie oben ausgeführt, sind die Überprüfungen vom Standpunkt der Leistung aus nicht unbedingt trivial. Viele sind wahrscheinlich trivial, aber selbst die Standardbibliothek verwendet sie und kann die Leistung in vielen Fällen auf inakzeptable Weise beeinträchtigen, wenn beispielsweise das Durchlaufen von Direktzugriffen
std::vector
in einem angeblich optimierten Release-Build viermal so lange gedauert hat Aufgrund seiner Grenzen sollte die Überprüfung niemals scheitern.In einem früheren Team mussten wir in unserer Matrix- und Vektorbibliothek einige Asserts in bestimmten kritischen Pfaden ausschließen, um Debugbuilds schneller auszuführen, da diese Asserts die mathematischen Operationen um eine Größenordnung bis zu dem Punkt verlangsamten, an dem sie ausgeführt wurden Ab sofort müssen wir 15 Minuten warten, bevor wir den Code von Interesse nachvollziehen können. Meine Kollegen wollten eigentlich nur die entfernen
asserts
direkt, weil sie fanden, dass gerade das einen gewaltigen Unterschied ausmachte. Stattdessen haben wir uns darauf festgelegt, dass kritische Debug-Pfade diese vermeiden. Wenn diese kritischen Pfade die Vektor- / Matrixdaten direkt verwenden, ohne die Begrenzungsprüfung zu durchlaufen, wurde die für die Durchführung der vollständigen Operation (die mehr als nur Vektor- / Matrixmathematik umfasste) erforderliche Zeit von Minuten auf Sekunden reduziert. Das ist also ein extremer Fall, aber die Aussagen sind definitiv nicht immer vernachlässigbar, auch nicht in der Nähe.Aber auch so ist es halt so
asserts
gestaltet. Wenn sie nicht auf ganzer Linie eine so große Auswirkung auf die Leistung hatten, würde ich es bevorzugen, wenn sie mehr als eine Debug-Build-Funktion wären, oder wir könnten eine Funktion verwenden,vector::at
die die Überprüfung der Grenzen auch bei Release-Builds und Throws on out-of-bounds einschließt Zugriff, zB (noch mit einem riesigen Performance-Hit). Momentan finde ich ihr Design aufgrund der enormen Leistungseinbußen in meinen Fällen viel nützlicher als ein Feature, das nur für das Debuggen erstellt wird und bei derNDEBUG
Definition weggelassen wird. Für die Fälle, mit denen ich zumindest gearbeitet habe, ist es ein großer Unterschied, dass bei einem Release-Build keine Überprüfung der Integrität durchgeführt wird, die eigentlich niemals scheitern sollte.vector::at
gegenvector::operator[]
Ich denke, dass die Unterscheidung dieser beiden Methoden sowohl den Kern als auch die Alternative ausmacht: Ausnahmen.
vector::operator[]
Implementierungen, die normalerweiseassert
sicherstellen, dass der Zugriff außerhalb der Grenzen einen leicht reproduzierbaren Fehler auslöst, wenn versucht wird, auf einen Vektor außerhalb der Grenzen zuzugreifen. Die Bibliotheksimplementierer gehen jedoch davon aus, dass es in einem optimierten Release-Build keinen Cent kostet.In der Zwischenzeit
vector::at
wird bereitgestellt, was selbst in Release-Builds immer die Grenzen überschreitet, aber es hat eine Leistungsbeeinträchtigung bis zu dem Punkt, an dem ich oft viel mehr Code sehe,vector::operator[]
als verwendetvector::at
. Ein Großteil des Designs von C ++ spiegelt die Idee wider, "für das zu zahlen, was Sie verwenden / benötigen", und viele Leute bevorzugen es oftoperator[]
, was sich nicht einmal mit den Einschränkungen für das Einchecken von Release-Builds auf der Grundlage der Vorstellung, dass sie nichts tun, beschäftigt Es ist nicht erforderlich, dass die Grenzen in ihren optimierten Release-Builds überprüft werden. Wenn Assertions in Release-Builds aktiviert würden, wäre die Leistung dieser beiden Assertions plötzlich identisch und die Verwendung von Vector wäre immer langsamer als ein dynamisches Array. Ein großer Teil des Designs und des Nutzens von Assertions basiert auf der Idee, dass sie in einem Release-Build frei werden.release_assert
Dies ist interessant, nachdem Sie diese Absichten entdeckt haben. Natürlich wären die Anwendungsfälle für jeden anders, aber ich denke, ich würde eine Verwendung für einen finden,
release_assert
der die Prüfung durchführt und die Software abstürzt, die eine Zeilennummer und eine Fehlermeldung anzeigt, sogar in Release-Builds.Es wäre für einige obskure Fälle in meinem Fall, in denen ich nicht möchte, dass die Software ordnungsgemäß wiederhergestellt wird, wie es der Fall wäre, wenn eine Ausnahme ausgelöst wird. Ich möchte, dass es in solchen Fällen auch bei der Freigabe abstürzt, damit der Benutzer eine Zeilennummer erhält, um zu melden, wenn die Software auf etwas stößt, das niemals passieren sollte, und zwar immer noch im Bereich der Überprüfung auf Programmiererfehler, nicht auf externe Eingabefehler wie Ausnahmen, aber billig genug, um ohne Rücksicht auf die Kosten für die Veröffentlichung fertig zu werden.
Es gibt tatsächlich einige Fälle , in denen ich einen harten Absturz mit einer Zeilennummer und Fehlermeldung finden würde bevorzugt zu anmutig erholt sich von einer geworfenen Ausnahme , die billig genug , um in einem Release zu halten sein könnte. In einigen Fällen ist es nicht möglich, eine Ausnahme zu beheben, z. B. beim Versuch, eine vorhandene Ausnahme zu beheben. Dort würde ich eine perfekte Passform für eine finden,
release_assert(!"This should never, ever happen! The software failed to fail!");
und das wäre natürlich spottbillig, da die Prüfung in erster Linie auf einem außergewöhnlichen Pfad durchgeführt würde und auf normalen Ausführungspfaden nichts kosten würde.quelle
Additionally, the performance argument for me only counts when it is a measurable problem.
also darum, von Fall zu Fall zu entscheiden, wann eine Behauptung aus der Veröffentlichung genommen werden soll.assert
das auf denselben_DEBUG/NDEBUG
Präprozessordefekten beruht, die Sie bei der Verwendung desassert
Makros verwenden würden. Es gibt also keine Möglichkeit, Zusicherungen selektiv nur für einen Codeteil zu aktivieren, ohne sie auch für die Standardbibliothek zu aktivieren, z. B. vorausgesetzt, sie verwendet die Standardbibliothek.assert
.vector::operator[]
undvector::at
würde zum Beispiel praktisch die gleiche Leistung haben, wenn Assertions in Release-Builds aktiviert wären, und es wäreoperator[]
vom Leistungsstandpunkt aus nicht mehr sinnvoll, sie zu verwenden, da sie ohnehin die Grenzüberprüfung durchführen würde.Ich programmiere in Ruby, nicht in C / C ++, und spreche daher nicht über den Unterschied zwischen Zusicherungen und Ausnahmen, sondern möchte darüber als eine Sache sprechen , die die Laufzeit stoppt . Ich bin mit den meisten Antworten oben nicht einverstanden, da das Anhalten des Programms mit dem Drucken eines Backtraces für mich als defensive Programmiertechnik gut funktioniert .
Wenn es eine Möglichkeit gibt, die Assert-Routine aufzurufen (ganz gleich, wie sie syntaktisch geschrieben ist und ob das Wort "assert" verwendet wird oder in der Programmiersprache oder in dsl überhaupt vorhanden ist), bedeutet dies, dass einige Arbeiten durchgeführt werden müssen und das Produkt geht sofort von "freigegeben, einsatzbereit" zurück zu "Needs Patch" - entweder umschreiben auf echte Ausnahmebehandlung oder einen Fehler beheben, der dazu führte, dass falsche Daten angezeigt wurden.
Ich meine, Assert ist keine Sache, mit der man leben und häufig telefonieren sollte - es ist ein Stoppsignal, das anzeigt, dass man etwas tun sollte, damit es nie wieder vorkommt. Und zu sagen, dass "Release Build sollte keine Asserts haben" ist wie zu sagen, dass "Release Build sollte keine Bugs haben" - Alter, es ist fast unmöglich, damit umzugehen.
Oder denken Sie an sie als an "Fehlgeschlagene Unittests, die vom Endbenutzer erstellt und ausgeführt werden". Sie können nicht vorhersagen, was der Benutzer mit Ihrem Programm machen wird, aber wenn etwas zu ernstes schief geht, sollte es anhalten - ähnlich wie beim Erstellen von Pipelines - Sie halten den Prozess an und veröffentlichen nicht, oder? ? Die Behauptung zwingt den Benutzer, anzuhalten, zu melden und auf Ihre Hilfe zu warten.
quelle