Ist das Böse behaupten? [geschlossen]

199

Die GoSprachschöpfer schreiben :

Go liefert keine Aussagen. Sie sind zweifellos praktisch, aber wir haben die Erfahrung gemacht, dass Programmierer sie als Krücke verwenden, um nicht über eine ordnungsgemäße Fehlerbehandlung und Berichterstattung nachzudenken. Eine ordnungsgemäße Fehlerbehandlung bedeutet, dass Server nach nicht schwerwiegenden Fehlern weiterarbeiten, anstatt abzustürzen. Eine ordnungsgemäße Fehlerberichterstattung bedeutet, dass die Fehler direkt und auf den Punkt gebracht werden, sodass der Programmierer keine großen Absturzabläufe interpretieren kann. Genaue Fehler sind besonders wichtig, wenn der Programmierer, der die Fehler sieht, mit dem Code nicht vertraut ist.

Was ist Ihre Meinung dazu?

Frank
quelle
4
Tangente: Go ist eine Sprache mit ungewöhnlicher Meinung. Das ist nicht unbedingt eine schlechte Sache. Es bedeutet jedoch, dass Sie seine Meinung mit einem größeren Salzkorn vertreten sollten. Es bedeutet auch, dass Sie, wenn Sie nicht einverstanden sind, Ihre Zähne zusammenbeißen, wenn Sie die Sprache verwenden. Als Beweis dafür, wie Go trotz der Realität an seinen Meinungen festhält, sollten Sie auf die Magie der Reflexion zurückgreifen, um festzustellen, ob zwei Sammlungen gleich sind.
Allyourcode
@allyourcode Wenn Sie sich beziehen reflect.DeepEqual, brauchen Sie es sicherlich nicht . Es ist praktisch, aber auf Kosten der Leistung (Unit-Tests sind ein guter Anwendungsfall). Andernfalls können Sie die für Ihre "Sammlung" geeignete Gleichheitsprüfung problemlos implementieren.
Igor Dubinskiy
1
Nein, darüber spreche ich nicht. Es gibt kein Slice1 == Slice2 ohne Reflexion. Alle anderen Sprachen haben ein Äquivalent zu dieser super einfachen Operation. Der einzige Grund, warum Go dies nicht tut, sind Vorurteile.
Allyourcode
Sie können zwei Slices ohne Reflexion mit einer forSchleife in Go vergleichen (genau wie C). Es wäre wirklich schön, generische Slice-Operationen zu haben, obwohl der Vergleich kompliziert wird, wenn Zeiger und Strukturen beteiligt sind.
Kbolino

Antworten:

321

Nein, es ist nichts falsch daran, assertsolange Sie es wie vorgesehen verwenden.

Das heißt, es soll dazu dienen, Fälle abzufangen, die beim Debuggen "nicht passieren können", im Gegensatz zur normalen Fehlerbehandlung.

  • Assert: Ein Fehler in der Programmlogik.
  • Fehlerbehandlung: Eine fehlerhafte Eingabe oder ein fehlerhafter Systemstatus, der nicht auf einen Fehler im Programm zurückzuführen ist.
caf
quelle
109

Nein, weder gotonochassert sind böse. Aber beide können missbraucht werden.

Assert ist für die Überprüfung der geistigen Gesundheit. Dinge, die das Programm beenden sollten, wenn sie nicht korrekt sind. Nicht zur Validierung oder als Ersatz für die Fehlerbehandlung.

gahooa
quelle
wie man mit gotoBedacht umgeht?
ar2015
1
@ ar2015 Finden Sie eines der absurd erfundenen Muster, die manche Leute gotoaus rein religiösen Gründen vermeiden möchten, und verwenden Sie dann einfach, gotoanstatt zu verschleiern, was Sie tun. Mit anderen Worten: Wenn Sie beweisen können, dass Sie wirklich brauchen goto, und die einzige Alternative darin besteht, eine Menge sinnloser Gerüste zu bauen, die letztendlich dasselbe tun, ohne jedoch die Goto-Polizei zu verändern ... dann verwenden Sie einfach goto. Voraussetzung dafür ist natürlich das Bit "Wenn Sie beweisen können, dass Sie es wirklich brauchen goto". Oft tun es die Leute nicht. Das bedeutet immer noch nicht, dass es von Natur aus eine schlechte Sache ist.
underscore_d
2
gotowird im Linux-Kernel für die Code-Bereinigung verwendet
Malat
61

Nach dieser Logik sind Haltepunkte auch böse.

Asserts sollten als Debugging-Hilfe verwendet werden und sonst nichts. "Böse" ist, wenn Sie versuchen, sie anstelle der Fehlerbehandlung zu verwenden.

Asserts sollen Ihnen als Programmierer helfen, Probleme zu erkennen und zu beheben, die nicht existieren dürfen, und überprüfen, ob Ihre Annahmen zutreffen.

Sie haben nichts mit Fehlerbehandlung zu tun, aber leider missbrauchen einige Programmierer sie als solche und erklären sie dann für "böse".

jalf
quelle
40

Ich benutze gerne behaupten viel. Ich finde es sehr nützlich, wenn ich zum ersten Mal Anwendungen erstelle (möglicherweise für eine neue Domain). Anstatt eine sehr ausgefallene Fehlerprüfung durchzuführen (die ich als vorzeitige Optimierung betrachten würde), codiere ich schnell und füge viele Asserts hinzu. Nachdem ich mehr über die Funktionsweise der Dinge weiß, schreibe ich einige der Zusicherungen neu, entferne sie und ändere sie zur besseren Fehlerbehandlung.

Aufgrund von Behauptungen verbringe ich viel weniger Zeit mit dem Codieren / Debuggen von Programmen.

Mir ist auch aufgefallen, dass mir die Behauptungen helfen, über viele Dinge nachzudenken, die meine Programme beschädigen könnten.

Arhuaco
quelle
31

Als zusätzliche Information bietet go eine integrierte Funktion panic . Dies kann anstelle von verwendet werden assert. Z.B

if x < 0 {
    panic("x is less than 0");
}

panicdruckt den Stack-Trace, hat also in gewisser Weise den Zweck von assert.

Yuku
quelle
30

Sie sollten zur Erkennung von Fehlern im Programm verwendet werden. Keine schlechte Benutzereingabe.

Bei richtiger Anwendung sind sie nicht böse.

Alex Budovski
quelle
13

Dies kommt häufig vor, und ich denke, ein Problem, das die Verteidigung von Behauptungen verwirrend macht, besteht darin, dass sie häufig auf der Überprüfung von Argumenten beruhen. Betrachten Sie also dieses andere Beispiel, wann Sie eine Behauptung verwenden könnten:

build-sorted-list-from-user-input(input)

    throw-exception-if-bad-input(input)

    ...

    //build list using algorithm that you expect to give a sorted list

    ...

    assert(is-sorted(list))

end

Sie verwenden eine Ausnahme für die Eingabe, da Sie erwarten, dass Sie manchmal schlechte Eingaben erhalten. Sie behaupten, dass die Liste sortiert ist, um Ihnen zu helfen, einen Fehler in Ihrem Algorithmus zu finden, den Sie per Definition nicht erwarten. Die Behauptung befindet sich nur im Debug-Build. Obwohl die Prüfung teuer ist, macht es Ihnen nichts aus, sie bei jedem einzelnen Aufruf der Routine auszuführen.

Sie müssen Ihren Produktionscode noch einem Unit-Test unterziehen, aber dies ist eine andere und ergänzende Methode, um sicherzustellen, dass Ihr Code korrekt ist. Unit-Tests stellen sicher, dass Ihre Routine der Benutzeroberfläche gerecht wird, während Assertions eine genauere Methode darstellen, um sicherzustellen, dass Ihre Implementierung genau das tut, was Sie von ihr erwarten.

jtolle
quelle
8

Behauptungen sind nicht böse, können aber leicht missbraucht werden. Ich stimme der Aussage zu, dass "Behauptungen häufig als Krücke verwendet werden, um nicht über eine ordnungsgemäße Fehlerbehandlung und Berichterstattung nachzudenken". Ich habe das ziemlich oft gesehen.

Persönlich verwende ich gerne Behauptungen, weil sie Annahmen dokumentieren, die ich möglicherweise beim Schreiben meines Codes gemacht habe. Wenn diese Annahmen während der Pflege des Codes verletzt werden, kann das Problem während des Tests erkannt werden. Ich lege jedoch Wert darauf, jede Behauptung aus meinem Code zu entfernen, wenn ich einen Produktionsbuild durchführe (dh mit #ifdefs). Indem ich die Behauptungen im Produktionsaufbau streife, eliminiere ich das Risiko, dass jemand sie als Krücke missbraucht.

Es gibt auch ein anderes Problem mit Behauptungen. Zusicherungen werden nur zur Laufzeit überprüft. Es ist jedoch häufig der Fall, dass die Prüfung, die Sie durchführen möchten, zur Kompilierungszeit durchgeführt wurde. Es ist vorzuziehen, ein Problem beim Kompilieren zu erkennen. Für C ++ - Programmierer bietet boost BOOST_STATIC_ASSERT, mit dem Sie dies tun können. Für C-Programmierer beschreibt dieser Artikel ( Linktext ) eine Technik, mit der Assertions zur Kompilierungszeit ausgeführt werden können.

Zusammenfassend lautet die Faustregel, die ich befolge: Verwenden Sie keine Zusicherungen in einem Produktionsbuild und verwenden Sie nach Möglichkeit nur Zusicherungen für Dinge, die zur Kompilierungszeit nicht überprüft werden können (dh zur Laufzeit überprüft werden müssen).

figurassa
quelle
5

Ich gebe zu, Asserts verwendet zu haben, ohne die ordnungsgemäße Fehlerberichterstattung in Betracht zu ziehen. Dies bedeutet jedoch nicht, dass sie bei korrekter Verwendung sehr hilfreich sind.

Sie sind besonders nützlich, wenn Sie dem "Crash Early" -Prinzip folgen möchten. Angenommen, Sie implementieren einen Referenzzählmechanismus. An bestimmten Stellen in Ihrem Code wissen Sie, dass die Nachzählung null oder eins sein sollte. Nehmen wir außerdem an, dass das Programm nicht sofort abstürzt, wenn der Refcount falsch ist. In der nächsten Nachrichtenschleife ist es jedoch schwierig herauszufinden, warum ein Fehler aufgetreten ist. Eine Behauptung wäre hilfreich gewesen, um den Fehler näher an seinem Ursprung zu erkennen.

StackedCrooked
quelle
5

Ich bevorzuge es, Code zu vermeiden, der beim Debuggen und Freigeben verschiedene Aufgaben ausführt.

Es ist jedoch nützlich, den Debugger unter einer Bedingung einzuschalten und alle Datei- / Zeileninformationen zu haben, auch den genauen Ausdruck und den genauen Wert.

Eine Behauptung, die "den Zustand nur beim Debuggen bewerten würde", kann eine Leistungsoptimierung sein und ist daher nur in 0,0001% der Programme nützlich - wo die Leute wissen, was sie tun. In allen anderen Fällen ist dies schädlich, da der Ausdruck den Programmstatus tatsächlich ändern kann:

assert(2 == ShroedingersCat.GetNumEars()); würde das Programm dazu bringen, verschiedene Dinge beim Debuggen und Freigeben zu tun.

Wir haben eine Reihe von Assert-Makros entwickelt, die eine Ausnahme auslösen und dies sowohl in der Debug- als auch in der Release-Version tun. Zum Beispiel THROW_UNLESS_EQ(a, 20);würde eine Ausnahme mit der Nachricht what () ausgelöst, die sowohl Datei-, Zeilen- als auch die tatsächlichen Werte von a usw. enthält. Nur ein Makro hätte die Macht dafür. Der Debugger kann so konfiguriert sein, dass er beim "Auslösen" des spezifischen Ausnahmetyps unterbrochen wird.

Pavel Radzivilovsky
quelle
4
90% der in Argumenten verwendeten Statistiken sind falsch.
João Portela
5

Ich mag Behauptungen nicht sehr. Ich würde nicht so weit gehen zu sagen, dass sie böse sind.

Grundsätzlich wird eine Zusicherung dasselbe tun wie eine ungeprüfte Ausnahme. Die einzige Ausnahme besteht darin, dass die Zusicherung (normalerweise) nicht für das Endprodukt aufbewahrt werden sollte.

Wenn Sie beim Debuggen und Erstellen des Systems ein Sicherheitsnetz für sich selbst erstellen, warum sollten Sie dieses Sicherheitsnetz Ihrem Kunden, Ihrem Support-Helpdesk oder jedem, der die von Ihnen derzeit erstellte Software verwenden kann, verweigern? Verwenden Sie Ausnahmen ausschließlich für Behauptungen und Ausnahmesituationen. Durch das Erstellen einer geeigneten Ausnahmehierarchie können Sie sehr schnell voneinander unterscheiden. Außer diesmal bleibt die Zusicherung bestehen und kann im Falle eines Fehlers, der sonst verloren gehen würde, wertvolle Informationen liefern.

Daher verstehe ich die Entwickler von Go vollständig, indem ich Asserts vollständig entferne und Programmierer dazu zwinge, Ausnahmen zu verwenden, um mit der Situation umzugehen. Es gibt eine einfache Erklärung dafür, Ausnahmen sind nur ein besserer Mechanismus für den Job, warum bei den archaischen Behauptungen bleiben?

Newtopian
quelle
Go hat keine Ausnahmen. Der übliche Grund, eine Zusicherung anstelle einer Ausnahme zu verwenden, besteht darin, dass Sie sie aus Leistungsgründen bei der Bereitstellung entfernen möchten. Behauptungen sind nicht archaisch. Es tut mir leid, dass ich hart klinge, aber diese Antwort ist weder im entferntesten hilfreich für die ursprüngliche Frage noch richtig.
Nir Friedman
3

Kurze Antwort: Nein, ich glaube, Behauptungen können nützlich sein

Brendan Lesniak
quelle
3

Ich habe kürzlich damit begonnen, meinem Code einige Asserts hinzuzufügen, und so habe ich es gemacht:

Ich teile meinen Code mental in Grenzcode und internen Code auf. Grenzcode ist Code, der Benutzereingaben verarbeitet, Dateien liest und Daten aus dem Netzwerk abruft. In diesem Code fordere ich eine Eingabe in einer Schleife an, die nur beendet wird, wenn die Eingabe gültig ist (bei interaktiver Benutzereingabe), oder bei nicht wiederherstellbaren beschädigten Datei- / Netzwerkdaten Ausnahmen auszulösen.

Interner Code ist alles andere. Beispielsweise kann eine Funktion, die eine Variable in meiner Klasse festlegt, als definiert werden

void Class::f (int value) {
    assert (value < end);
    member = value;
}

und eine Funktion, die Eingaben von einem Netzwerk erhält, könnte als solche lauten:

void Class::g (InMessage & msg) {
    int const value = msg.read_int();
    if (value >= end)
        throw InvalidServerData();
    f (value);
}

Dies gibt mir zwei Ebenen von Schecks. Alles, wo die Daten zur Laufzeit ermittelt werden, erhält immer eine Ausnahme oder sofortige Fehlerbehandlung. Dieses zusätzliche Einchecken Class::fmit der assertAnweisung bedeutet jedoch, dass Class::fich immer noch eine Überprüfung der geistigen Gesundheit habe , wenn jemals ein interner Code aufgerufen wird. Mein interner Code übergibt möglicherweise kein gültiges Argument (da ich möglicherweise valueaus einer komplexen Reihe von Funktionen berechnet habe ). Daher möchte ich, dass die Behauptung in der Einstellungsfunktion dokumentiert, dass unabhängig davon, wer die Funktion aufruft, valuenicht größer als oder sein darf gleich end.

Dies scheint in das zu passen, was ich an einigen Stellen lese, dass Behauptungen in einem gut funktionierenden Programm unmöglich zu verletzen sein sollten, während Ausnahmen für außergewöhnliche und fehlerhafte Fälle gelten sollten, die noch möglich sind. Da ich theoretisch alle Eingaben validiere, sollte es nicht möglich sein, dass meine Behauptung ausgelöst wird. Wenn ja, ist mein Programm falsch.

David Stone
quelle
2

Wenn die Behauptungen, von denen Sie sprechen, bedeuten, dass sich das Programm erbricht und dann existiert, können Behauptungen sehr schlecht sein. Das heißt nicht, dass sie es immer sind falsch verwendet werden, sondern ein Konstrukt, das sehr leicht missbraucht werden kann. Sie haben auch viele bessere Alternativen. Solche Dinge sind gute Kandidaten, um als böse bezeichnet zu werden.

Beispielsweise sollte ein Modul eines Drittanbieters (oder wirklich ein beliebiges Modul) das aufrufende Programm fast nie verlassen. Dies gibt dem aufrufenden Programmierer keine Kontrolle darüber, welches Risiko das Programm in diesem Moment eingehen sollte. In vielen Fällen sind Daten so wichtig, dass selbst das Speichern beschädigter Daten besser ist als das Verlieren dieser Daten. Asserts können Sie zwingen, Daten zu verlieren.

Einige Alternativen zu Behauptungen:

  • Verwenden eines Debuggers,
  • Konsole / Datenbank / andere Protokollierung
  • Ausnahmen
  • Andere Arten der Fehlerbehandlung

Einige Referenzen:

Sogar Leute, die sich für die Behauptung einsetzen, denken, sie sollten nur in der Entwicklung und nicht in der Produktion verwendet werden:

Diese Person sagt, dass Asserts verwendet werden sollten, wenn das Modul möglicherweise Daten beschädigt hat, die nach dem Auslösen einer Ausnahme bestehen bleiben: http://www.advogato.org/article/949.html . Dies ist sicherlich ein vernünftiger Punkt. Ein externes Modul sollte jedoch niemals vorschreiben, wie wichtig beschädigte Daten für das aufrufende Programm sind (indem es "für" sie beendet). Der richtige Weg, dies zu handhaben, besteht darin, eine Ausnahme auszulösen, die deutlich macht, dass sich das Programm jetzt möglicherweise in einem inkonsistenten Zustand befindet. Und da gute Programme meistens aus Modulen bestehen (mit ein wenig Klebercode in der ausführbaren Hauptdatei), sind Asserts fast immer das Falsche.

BT
quelle
1

assert ist sehr nützlich und kann Ihnen viel Backtracking ersparen, wenn unerwartete Fehler auftreten, indem Sie das Programm bei den ersten Anzeichen von Problemen anhalten.

Andererseits ist es sehr leicht zu missbrauchen assert.

int quotient(int a, int b){
    assert(b != 0);
    return a / b;
}

Die richtige, korrekte Version wäre ungefähr so:

bool quotient(int a, int b, int &result){
    if(b == 0)
        return false;

    result = a / b;
    return true;
}

Also ... auf lange Sicht ... im Großen und Ganzen ... muss ich zustimmen, dass assertdas missbraucht werden kann. Das mache ich die ganze Zeit.

Agnel Kurian
quelle
1

assert wird zur Fehlerbehandlung missbraucht, weil weniger getippt wird.

Als Sprachdesigner sollten sie daher eher darauf achten, dass eine ordnungsgemäße Fehlerbehandlung mit noch geringerer Eingabe möglich ist. Das Ausschließen von Assert, weil Ihr Ausnahmemechanismus ausführlich ist, ist nicht die Lösung. Oh warte, Go hat auch keine Ausnahmen. Schade :)

akuhn
quelle
1
Nicht schlecht :-) Ausnahmen oder nicht, Behauptungen oder nicht, Go-Fans reden immer noch darüber, wie kurz die Codes sind.
Moshe Revah
1

Ich wollte dem Autor in den Kopf treten, als ich das sah.

Ich verwende Asserts die ganze Zeit im Code und ersetze sie schließlich alle, wenn ich mehr Code schreibe. Ich verwende sie, wenn ich die erforderliche Logik nicht geschrieben habe und benachrichtigt werden möchte, wenn ich auf den Code stoße, anstatt eine Ausnahme zu schreiben, die gelöscht wird, wenn sich das Projekt dem Abschluss nähert.

Ausnahmen fügen sich auch leichter in den Produktionscode ein, was mir nicht gefällt. Eine Behauptung ist leichter zu bemerken alsthrow new Exception("Some generic msg or 'pretend i am an assert'");

Peter Mortensen
quelle
1

Mein Problem mit diesen Antworten zur Verteidigung der Behauptung ist, dass niemand klar spezifiziert, was sie von einem normalen schwerwiegenden Fehler unterscheidet und warum eine Behauptung keine Teilmenge einer Ausnahme sein kann . Was ist nun, wenn die Ausnahme nie abgefangen wird? Ist das eine Behauptung der Nomenklatur? Und warum sollten Sie jemals eine Einschränkung in der Sprache auferlegen wollen, dass eine Ausnahme ausgelöst werden kann, die / nichts / behandeln kann?

Evan Carroll
quelle
Wenn Sie sich meine Antwort ansehen. Meine Verwendung besteht darin, "Ausnahmen" (Asserts), die ich für das Debuggen verwenden möchte, von Ausnahmen zu unterscheiden, die ich behalte. Warum sollte ich sie loswerden wollen? denn ohne sie wäre es nicht vollständig. Beispiel ist, wenn ich 3 Fälle behandle und der 4. todo ist. Ich kann leicht nach Assert suchen, um sie im Code zu finden, und weiß, dass sie unvollständig sind, anstatt eine Ausnahme zu verwenden, die möglicherweise versehentlich (von einem anderen Programmierer) abgefangen wird oder schwer zu sagen ist, ob es sich um eine Ausnahme oder eine Logikprüfung handelt, die ich im Code lösen sollte.
In meinen Augen ist dies eine schlechte Idee, auf dem gleichen Niveau wie "versiegelte" Klassen und aus dem gleichen Grund. Sie gehen davon aus, dass die Ausnahmen, die Sie beibehalten möchten, für die Verwendung Ihres Codes, den Sie noch nicht kennen, akzeptabel sind. Alle Ausnahmen laufen über dieselben Kanäle, und wenn der Benutzer sie nicht abfangen möchte, kann er sich dafür entscheiden, dies nicht zu tun. Wenn er das tut, sollte er auch die Fähigkeit haben. In jedem Fall machen Sie nur Annahmen oder schieben Ihre Praxis mit einem Konzept wie einer Behauptung ab.
Evan Carroll
Ich entschied, dass Beispielszenarien am besten sind. Hier ist eine einfache. int func (int i) {if (i> = 0) {console.write ("Die Zahl ist positiv {0}", i); } else {assert (false); // zu faul, um negative Geldautomaten zu machen} return i * 2; <- Wie würde ich das ohne Behauptungen machen und ist eine Ausnahme wirklich besser? und denken Sie daran, dieser Code wird vor der Veröffentlichung implementiert.
Sicher, Ausnahmen sind besser. Nehmen wir an, ich nehme Benutzereingaben entgegen und rufe func()mit einer negativen Nummer an. Jetzt, plötzlich mit Ihren Behauptungen, haben Sie den Teppich unter mir herausgezogen und mir keine Chance gegeben, mich zu erholen, anstatt mir höflich zu sagen, was ich verlange, kann nicht getan werden. Es ist nichts Falsches daran, das Programm zu beschuldigen, sich schlecht benommen zu haben und es zu zitieren: Das Problem ist, dass Sie den Akt der Durchsetzung eines Gesetzes verwischen und den Verbrecher verurteilen.
Evan Carroll
Das ist der Punkt, Sie sollten nicht sagen, was der Benutzer tun möchte, kann nicht getan werden. Die App sollte mit der Fehlermeldung enden und wer auch immer debuggt, würde sich daran erinnern, dass etwas getan werden sollte, aber nicht. Sie möchten nicht, dass es behandelt wird. Sie möchten eine Kündigung und möchten daran erinnert werden, dass Sie diesen Fall nicht bearbeitet haben. und es ist extrem einfach zu sehen, welche Fälle noch übrig sind, da Sie nur nach Assert im Code suchen müssen. Die Behandlung des Fehlers wäre falsch, da der Code dies tun sollte, sobald er für die Produktion bereit ist. Es ist falsch, einem Programmierer zu erlauben, es zu fangen und etwas anderes zu tun.
1

Ja, Behauptungen sind böse.

Oft werden sie an Orten eingesetzt, an denen eine ordnungsgemäße Fehlerbehandlung angewendet werden sollte. Gewöhnen Sie sich von Anfang an daran, die richtige Fehlerbehandlung in der Produktionsqualität zu schreiben!

Normalerweise behindern sie das Schreiben von Komponententests (es sei denn, Sie schreiben eine benutzerdefinierte Zusicherung, die mit Ihrem Testgeschirr interagiert). Dies liegt häufig daran, dass sie dort eingesetzt werden, wo eine ordnungsgemäße Fehlerbehandlung angewendet werden sollte.

Meistens werden sie aus Release-Builds kompiliert, was bedeutet, dass keiner ihrer "Tests" verfügbar ist, wenn Sie den Code ausführen, den Sie tatsächlich veröffentlichen. Angesichts der Tatsache, dass in Multithread-Situationen die schlimmsten Probleme häufig nur im Release-Code auftreten, kann dies schlimm sein.

Manchmal sind sie eine Krücke für ansonsten kaputte Designs; Das heißt, das Design des Codes ermöglicht es einem Benutzer, ihn so aufzurufen, dass er nicht aufgerufen werden sollte, und die Behauptung "verhindert" dies. Korrigieren Sie das Design!

Ich habe 2005 in meinem Blog darüber mehr geschrieben: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html

Len Holgate
quelle
0

Nicht so sehr böse als generell kontraproduktiv. Es gibt eine Trennung zwischen permanenter Fehlerprüfung und Debugging. Assert lässt die Leute denken, dass jedes Debuggen dauerhaft sein sollte und verursacht massive Lesbarkeitsprobleme, wenn es häufig verwendet wird. Die permanente Fehlerbehandlung sollte besser sein als bei Bedarf, und da die Behauptung eigene Fehler verursacht, ist dies eine ziemlich fragwürdige Praxis.

Charles Eli Käse
quelle
5
assert ist gut geeignet, um die Voraussetzungen oben in einer Funktion zu deklarieren, und fungiert, wenn es klar geschrieben ist, als Teil der Dokumentation der Funktion.
Peter Cordes
0

Ich benutze niemals assert (), Beispiele zeigen normalerweise so etwas:

int* ptr = new int[10];
assert(ptr);

Das ist schlecht, ich mache das nie. Was ist, wenn mein Spiel ein paar Monster zuweist? Warum sollte ich das Spiel zum Absturz bringen? Stattdessen sollten Sie die Fehler ordnungsgemäß behandeln. Tun Sie also etwas wie:

CMonster* ptrMonsters = new CMonster[10];
if(ptrMonsters == NULL) // or u could just write if(!ptrMonsters)
{
    // we failed allocating monsters. log the error e.g. "Failed spawning 10 monsters".
}
else
{
    // initialize monsters.
}
Bob
quelle
14
newkehrt nie zurück nullptr, es wirft.
David Stone
Beachten Sie, dass Sie dafür std :: nothrow verwenden können .
Markand