Empfehlen eines Entwurfsmusters / Ansatzes zum Offenlegen / Tolerieren / Beheben von Systemfehlern, Ausnahmebehandlung (z. B. in Java, C ++, Perl, PHP)

13

Können Sie ein Entwurfsmuster / einen Ansatz zum Offenlegen / Tolerieren / Wiederherstellen von Systemfehlern, Ausnahmebehandlung (Java, C ++, Perl, PHP) empfehlen?

Einige Fehler müssen gemeldet werden.

Einige Fehler können intern behandelt werden (durch einen erneuten Versuch oder sind nicht relevant (können ignoriert werden).

Wie strukturieren Sie den Code, um sie zu fangen?

Es müssen aber alle Fehler protokolliert werden.

Welche Best Practices gibt es?

Und um sie zu simulieren, um Komponenten, die von ihnen betroffen sind, vollständig zu testen?

Allgemeine, nicht programmiersprachenspezifische Frage, die auf mehrere moderne Programmiersprachen anwendbar ist, würde jedoch beispielhafte Darstellungen von Mustern, Ansätzen und Philosophien in Java, C ++, PHP und Perl begrüßen.

(Auch in stackoverflow gefragt: /programming/7432596/recommend-a-design-pattern-approach-to-exposing-tolerating-recovering-from-system, aber ich dachte, es sollte auch auf Programmierer gefragt werden, weil Ich denke, die Fragen und Antworten der Programmierer decken umfassendere Software- / Programmierprobleme ab, während sich Stackoverflow mehr auf die technische Implementierung bezieht (IMHO).

wie Sie wissen
quelle
2
Für mich scheint Ihre Frage viel zu allgemein und offen zu sein, um effektiv beantwortet zu werden. Versuchen Sie, es auf einige spezifischere Fälle und auch auf bestimmte Anwendungstypen / Umgebungen (z. B. GUI-App / Server / ...) zu beschränken.
Péter Török
Siehe auch stackoverflow.com/questions/937285/…
Péter Török,
@ Péter Török, mikera gibt eine gute Antwort, wahrscheinlich akzeptieren sie ihre.
Therobyouknow

Antworten:

16

Schnelles Scheitern ist ein großartiger Entwurfsansatz und kann möglicherweise als Muster gewertet werden: http://en.wikipedia.org/wiki/Fail-fast

Ich habe auch eine Reihe von Grundsätzen für nützlich befunden:

  • Berücksichtigen Sie Ausnahmen als Teil der Schnittstelle zu den einzelnen Funktionen / Modulen - dh dokumentieren Sie sie und verwenden Sie, sofern dies in Ihrer Sprache unterstützt wird, aktivierte Ausnahmen.
  • Verstellen Sie niemals einen Fehler - wenn er fehlgeschlagen ist, versuchen Sie nicht, mit einem Versuch fortzufahren, "anzunehmen", wie fortzufahren ist. Zum Beispiel ist eine spezielle Behandlung für Null-Fälle für mich oft ein Codegeruch: Wenn Ihre Methode einen Nicht-Null-Wert benötigt, sollte sie sofort eine Ausnahme auslösen, wenn sie auf eine Null stößt (entweder NullPointerException oder idealerweise eine aussagekräftigere IllegalArgumentException).
  • Schreiben Sie Komponententests sowohl für Ausnahmefälle als auch für normale Fälle. Manchmal ist es schwierig, solche Tests einzurichten, aber es lohnt sich, wenn Sie sicherstellen möchten, dass Ihr System robust gegen Ausfälle ist
  • Protokollieren Sie an dem Punkt, an dem der Fehler abgefangen und behandelt wurde (vorausgesetzt, der Fehler war schwerwiegend genug, um protokolliert zu werden). Der Grund dafür ist, dass Sie die Ursache verstanden haben und einen Ansatz zur Behandlung des Fehlers hatten, sodass Sie die Protokollnachricht aussagekräftig machen können.
  • Verwenden Sie Ausnahmen nur für wirklich unerwartete Bedingungen / Fehler. Wenn Ihre Funktion auf eine Weise "fehlschlägt", die tatsächlich erwartet wird (z. B. Abfragen, ob mehr Eingaben verfügbar sind, und Auffinden von keiner), sollte sie eine normale Antwort zurückgeben ("keine Eingaben verfügbar") und keine Ausnahme auslösen
  • Schlagen Sie ordnungsgemäß fehl (Dank an Steven Lowe!) - bereinigen Sie vor dem Beenden, falls möglich, in der Regel, indem Sie Änderungen rückgängig machen, Transaktionen rückgängig machen oder Ressourcen in einer "Endgültig" -Anweisung oder einem gleichwertigen Kontoauszug freigeben. Die Bereinigung sollte idealerweise auf derselben Ebene erfolgen, auf der die Ressourcen gebunden wurden, um Klarheit und logische Konsistenz zu gewährleisten.
  • Wenn Sie scheitern müssen, scheitern Sie laut - eine Ausnahme, die kein Teil Ihres Codes verarbeiten konnte (dh auf die oberste Ebene durchgesickert ist, ohne aufgefangen zu werden), sollte einen sofortigen, lauten und sichtbaren Fehler verursachen, der Ihre Aufmerksamkeit darauf lenkt. Normalerweise halte ich das Programm oder die Task an und schreibe einen vollständigen Ausnahmebericht an System.out.
mikera
quelle
1
scheitern auch anmutig - bereinigen Sie vor dem Beenden, wenn überhaupt möglich
Steven A. Lowe
+1 @mikera für klare Punkte, was zu beachten ist. Wahrscheinlich akzeptierte Antwort, ich werde etwas länger offen lassen, damit andere dazu beitragen können.
Therobyouknow
+1 @Steve A. Lowe - für benutzerzentriertes Design. zB wie Dateien speichern, ohne temporäre Dateien liegen zu lassen. Siehe meine Frage zu "Datenhygiene" als verwandtes Thema in meiner Fragenliste.
Therobyouknow
5

Nachdem ich mit Ausnahmen in Java und .NET gearbeitet und viele Artikel gelesen hatte, in denen es darum ging, wie / wann / warum Ausnahmen abgefangen werden sollen, stellte ich mir schließlich die folgenden Schritte vor, die ich in meinem Kopf durcharbeite, wenn eine potenzielle Ausnahme auftritt oder eine Ausnahme muss ich fangen (Java) ... auch wenn es nie passiert (seufz ...). Und es scheint zumindest für mich zu funktionieren:

  1. Gibt es irgendetwas Nützliches, das ich mit dieser Ausnahme machen kann (außer Protokollierung)? Wenn die Antwort Ja lautet, schreiben Sie den Umgehungscode, und wenn die Umgehung Ausnahmen auslösen kann, fahren Sie mit Schritt 2 fort:
  2. Wickeln Sie die Ausnahme um eine Laufzeitausnahme, werfen Sie sie aus und fahren Sie mit Schritt 3 fort.
  3. Fangen Sie in der übergeordneten Klasse, in der eine mögliche Datenbank- / Prozesstransaktion initiiert wurde, die Ausnahme ab, setzen Sie die Transaktion zurück und lösen Sie die Ausnahme erneut aus.
  4. Protokollieren Sie in der höchsten Klasse (die möglicherweise die Klasse ist, in der die Transaktion initiiert wurde) die Ausnahme mit einem Protokollierungsframework wie slf4j ( z. B. gekoppelt mit log4j ) oder log4net . Senden Sie die Ausnahme nach Möglichkeit direkt per E-Mail an eine Verteilerliste, die sich aus Entwicklern der Anwendung zusammensetzt.
  5. Wenn eine GUI vorhanden ist, zeigen Sie eine Fehlermeldung an, die auf benutzerfreundliche Weise angibt, was das Problem verursacht hat. Zeigen Sie die Exception / Stacktrace nicht an, es ist dem Benutzer egal und er muss nicht wissen, dass es sich um eine NullPointerException handelt.

Ich sollte auch den Schritt 0 hinzufügen , in dem ich absichtlich eine so genannte "Business" -Ausnahme (eine neue Ausnahme, die ich durch Erweitern der Klasse "Exception" erstelle) auslöse, wenn eine komplexe Behandlung aufgrund von Datenfehlern nicht ausgeführt werden kann, ABER das Es ist bekannt, dass dies passiert, da sie während der Analyse als Ausnahmefälle identifiziert wurden.

Mit Ausnahme des Protokollierungsteils stimme ich den von "mikera" geschriebenen Punkten voll und ganz zu. Ich möchte nur hinzufügen, dass die Ausnahme nur einmal protokolliert werden sollte .

Die Schritte , die ich aufgelistet habe, können sich auch unterscheiden, wenn Sie eine API / ein Framework schreiben . Dort ist das Auslösen gut gestalteter Ausnahmen obligatorisch, um Entwicklern das Verständnis ihrer Fehler zu erleichtern.

Zum Testen der Ausnahmen sollten Sie mit Scheinobjekten in der Lage sein, fast alles zu testen, unabhängig davon, ob es sich um Ausnahmen handelt oder nicht, vorausgesetzt, Ihre Klassen respektieren die Best Practice "Eine Klasse, um eine Sache zu tun". Ich persönlich stelle auch sicher, dass die wichtigsten, aber verborgenen Methoden als "geschützt" anstatt als "privat" gekennzeichnet werden, damit ich sie ohne großen Aufwand testen kann. Abgesehen davon ist das Testen von Ausnahmen einfach. Sie müssen nur die Ausnahme provozieren und das Auftreten einer Ausnahme "erwarten", indem Sie sie abfangen. Wenn Sie keine Ausnahme erhalten, liegt ein Unit-Testfallfehler vor.

Jalayn
quelle
+1 @Jalayn für log4j als Ansatz erwähnen, das ist, was ich benutze, um es zu verstärken, zu wissen, dass es auch jemand anderes ist.
Therobyouknow
0

Bauen Sie Ihre Objekte richtig und machen Sie sich keine Sorgen um äußere Einflüsse. Wenn Sie sich dafür entscheiden, Ausnahmen zu nutzen, lassen Sie Ihre Objekte Ausnahmen auslösen, wenn sie bei etwas fehlschlagen .

Sobald alle Ihre Objekte ordnungsgemäß funktionieren, sollte es ziemlich einfach sein, eine saubere Hierarchie für die Fehlerbehandlung in Ihrem Entwurf zu erstellen.

Yam Marcovic
quelle