482 Stimmen

Warum sollte ich nicht jeden Block in "try"-"catch" einpacken?

Ich war schon immer der Überzeugung, dass es fahrlässig ist, einen Aufruf, der eine Ausnahme werfen kann, nicht mit einem sinnvollen try-Block zu schützen.

Ich habe gerade "Sie sollten IMMER Aufrufe, die eine Ausnahme werfen können, in try-catch-Blöcke einpacken." zu dieser Frage gepostet und mir wurde gesagt, dass es sich um 'bemerkenswert schlechten Rat' handelt - Ich würde gerne verstehen, warum.

16voto

Kristopher Johnson Punkte 78933

Wie in anderen Antworten bereits erwähnt, sollten Sie eine Ausnahme nur abfangen, wenn Sie eine Art vernünftige Fehlerbehandlung durchführen können.

Zum Beispiel in der Frage, die Ihre Frage inspiriert hat, fragt der Fragesteller, ob es sicher ist, Ausnahmen für einen lexical_cast von einem Integer zu einem String zu ignorieren. Ein solcher Cast sollte niemals fehlschlagen. Wenn es fehlschlägt, ist im Programm etwas gründlich schiefgegangen. Was könnten Sie in dieser Situation tun, um sich zu erholen? Es ist wahrscheinlich am besten, das Programm einfach sterben zu lassen, da es sich in einem Zustand befindet, dem nicht vertraut werden kann. Daher ist es möglicherweise das sicherste, die Ausnahme nicht zu behandeln.

12voto

starblue Punkte 53167

Wenn Sie Ausnahmen immer sofort im Aufrufer einer Methode behandeln, die eine Ausnahme werfen kann, werden Ausnahmen nutzlos, und Sie sollten besser Fehlercodes verwenden.

Der ganze Sinn von Ausnahmen besteht darin, dass sie nicht in jeder Methode in der Aufrufkette behandelt werden müssen.

10voto

Donal Fellows Punkte 125686

Der beste Rat, den ich gehört habe, ist, dass Sie Ausnahmen nur an Stellen abfangen sollten, an denen Sie vernünftigerweise etwas gegen den Ausnahmefall tun können, und dass "Abfangen, Protokollieren und Freigeben" keine gute Strategie ist (wenn auch manchmal in Bibliotheken unvermeidlich).

2 Stimmen

@KeithB: Ich würde es als Zweitbeste Strategie betrachten. Es ist besser, wenn du das Log auf eine andere Weise schreiben kannst.

1 Stimmen

@KeithB: Es ist eine "besser als nichts in einer Bibliothek" Strategie. "Fangen, protokollieren, richtig damit umgehen" ist besser, wo es möglich ist. (Ja, ich weiß, dass es nicht immer möglich ist.)

8voto

user2502917 Punkte 319

Ich bekam die "Gelegenheit", mehrere Projekte zu retten, und die Führungskräfte ersetzten das gesamte Entwicklungsteam, weil die App zu viele Fehler hatte und die Benutzer die Probleme leid waren. Diese Code-Basen hatten alle eine zentrale Fehlerbehandlung auf App-Ebene, wie es die am höchsten bewertete Antwort beschreibt. Wenn diese Antwort die beste Praxis ist, warum hat sie nicht funktioniert und dem vorherigen Entwicklungsteam erlaubt, die Probleme zu lösen? Vielleicht funktioniert es manchmal nicht? Die obigen Antworten erwähnen nicht, wie lange Entwickler damit verbringen, einzelne Probleme zu beheben. Wenn die Zeit zur Fehlerbehebung das wichtigste Kriterium ist, ist es eine bessere Praxis, Code mit try..catch-Blöcken zu instrumentieren.

Wie hat mein Team die Probleme behoben, ohne das UI signifikant zu verändern? Ganz einfach, jede Methode wurde mit try..catch-Blöcken instrumentiert und alles wurde am Fehlerpunkt protokolliert, mit dem Methodennamen, den Methodenparameterwerten, die zu einem als Zeichenkette übergeben werden zusammen mit der Fehlermeldung, der Fehlermeldung, dem App-Namen, dem Datum und der Version. Mit diesen Informationen können Entwickler Analysen der Fehler durchführen, um die Ausnahme zu identifizieren, die am häufigsten auftritt! Oder der Namespace mit der höchsten Anzahl von Fehlern. Es kann auch validieren, dass ein Fehler, der in einem Modul auftritt, ordnungsgemäß behandelt wird und nicht durch mehrere Gründe verursacht wird.

Ein weiterer großer Vorteil dabei ist, dass die Entwickler einen Haltepunkt in der Fehlerprotokollierungsmethode setzen können und mit einem einzigen Klick auf die Schaltfläche "Ausführen" zum Fehlerzeitpunkt auf die Methode zugreifen können, wobei die eigentlichen Objekte im sofort verfügbaren Fenster erscheinen. Dies macht das Debuggen sehr einfach und ermöglicht es, die Ausführung zurück zum Start der Methode zu ziehen, um das Problem zu duplizieren und die genaue Zeile zu finden. Erlaubt die zentrale Ausnahmehandhabung einem Entwickler, eine Ausnahme in 30 Sekunden zu replizieren? Nein.

Die Aussage "Eine Methode sollte nur eine Ausnahme abfangen, wenn sie in irgendeiner vernünftigen Weise damit umgehen kann." Dies impliziert, dass Entwickler jeden Fehler vor der Veröffentlichung vorhersagen können oder auf ihn stoßen werden. Wenn dies der Fall wäre, bräuchte man keinen Top-Level-App-Ausnahmehandler und es gäbe keinen Markt für Elastic Search und Logstash.

Diese Methode ermöglicht es Entwicklern auch, intermittierende Probleme in der Produktion zu finden und zu beheben! Möchten Sie in der Produktion ohne Debugger debuggen? Oder würden Sie lieber Anrufe entgegennehmen und E-Mails von verärgerten Benutzern erhalten? Dies ermöglicht es Ihnen, Probleme zu beheben, bevor es jemand anderes bemerkt, ohne dass Sie E-Mails, IM oder Slack-Support benötigen, da alles Notwendige zur Fehlerbehebung sofort verfügbar ist. 95% der Probleme müssen nie reproduziert werden.

Um richtig zu funktionieren, muss diese Methode mit einer zentralisierten Protokollierung kombiniert werden, die den Namespace/Modul, den Klassennamen, die Methode, die Eingaben und die Fehlermeldung erfassen und in einer Datenbank speichern kann, damit sie aggregiert werden kann, um hervorzuheben, welche Methode am häufigsten fehlschlägt, damit sie zuerst behoben werden kann.

Manchmal entscheiden sich Entwickler dafür, Ausnahmen von einem Catch-Block aus dem Stapel herauszuwerfen, aber dieser Ansatz ist 100 Mal langsamer als normaler Code, der nicht wirft. Abfangen und freigeben mit Protokollierung wird bevorzugt.

Diese Technik wurde verwendet, um eine App schnell zu stabilisieren, die bei den meisten Benutzern in einem Fortune-500-Unternehmen alle Stunden versagte, entwickelt von 12 Entwicklern über 2 Jahre. Mit diesem Ansatz wurden 3000 verschiedene Ausnahmen identifiziert, behoben, getestet und innerhalb von 4 Monaten bereitgestellt. Das macht durchschnittlich alle 15 Minuten eine Behebung über 4 Monate hinweg.

Ich stimme zu, dass es keine Freude bereitet, alles zu tippen, was zur Codierungsinstrumentierung erforderlich ist, und ich ziehe es vor, den wiederholten Code nicht anzusehen, aber das Hinzufügen von 4 Zeilen Code zu jeder Methode lohnt sich langfristig.

3 Stimmen

Das Einwickeln jedes Blocks scheint übertrieben zu sein. Es macht deinen Code schnell aufgebläht und schwer zu lesen. Das Protokollieren eines Stapeltraces aus einer Ausnahme auf höheren Ebenen zeigt dir, wo das Problem aufgetreten ist, und das zusammen mit dem Fehler selbst ist im Allgemeinen genug Information, um voranzukommen. Mich würde interessieren, wo du das als nicht ausreichend betrachtet hast. Nur damit ich die Erfahrung einer anderen Person gewinnen kann.

2 Stimmen

"Ausnahmen sind 100 bis 1000 Mal langsamer als normaler Code und sollten niemals erneut ausgelöst werden" - diese Aussage trifft auf die meisten modernen Compiler und Hardware nicht zu.

0 Stimmen

Es scheint übertrieben und erfordert etwas Tipparbeit, aber ist der einzige Weg, um Analysen zu Ausnahmen durchzuführen, um die größten Fehler zuerst zu finden und zu beheben, einschließlich intermittierender Fehler in der Produktion. Der Catch-Block behandelt spezifische Fehler, falls erforderlich, und hat eine einzelne Codezeile, die protokolliert.

5voto

Mike Bailey Punkte 11981

Der Rat, den mir einmal mein Informatikprofessor gab, war: "Verwenden Sie Try- und Catch-Blöcke nur, wenn es nicht möglich ist, den Fehler mit Standardmitteln zu behandeln."

Zum Beispiel erklärte er uns, dass, wenn ein Programm an einer Stelle auf ein ernsthaftes Problem stößt, an der es nicht möglich ist, etwas wie:

int f()
{
    // Do stuff

    if (Bedingung == falsch)
        return -1;
    return 0;
}

int Bedingung = f();

if (f != 0)
{
    // Fehler behandeln
}

Dann sollten Sie try, catch Blöcke verwenden. Obwohl Sie Ausnahmen verwenden können, um dies zu behandeln, wird dies im Allgemeinen nicht empfohlen, da Ausnahmen leistungstechnisch teuer sind.

7 Stimmen

Das ist eine Strategie, aber viele Leute empfehlen, niemals Fehlercodes oder Erfolgs-/Fehlerstatus von Funktionen zurückzugeben, sondern stattdessen Ausnahmen zu verwenden. Die fehlerbasierte Fehlerbehandlung ist oft einfacher zu lesen als Code basierend auf Fehlercodes. (Siehe die Antwort von AshleysBrain zu dieser Frage für ein Beispiel.) Denken Sie auch immer daran, dass viele Informatikprofessoren nur wenig Erfahrung beim Schreiben von echtem Code haben.

1 Stimmen

-1 @Sagelika Deine Antwort besteht darin, Ausnahmen zu vermeiden, daher ist kein try-catch nötig.

3 Stimmen

@Kristopher: Ein weiterer großer Nachteil des Rückgabecodes ist, dass es sehr einfach ist, den Rückgabecode zu vergessen, und direkt nach dem Aufruf ist nicht unbedingt der beste Ort, um das Problem zu behandeln.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X