532 Stimmen

Das Argument gegen kontrollierte Ausnahmen

Seit einigen Jahren ist es mir nicht gelungen, eine vernünftige Antwort auf die folgende Frage zu finden: Warum sind einige Entwickler so gegen geprüfte Ausnahmen? Ich habe zahlreiche Gespräche geführt, Dinge in Blogs gelesen, gelesen, was Bruce Eckel zu sagen hatte (die erste Person, die ich sah, die sich gegen sie aussprach).

Ich schreibe gerade einen neuen Code und achte sehr genau darauf, wie ich mit Ausnahmen umgehe. Ich versuche, den Standpunkt der "Wir mögen keine geprüften Ausnahmen"-Leute zu verstehen, aber ich kann ihn immer noch nicht nachvollziehen.

Jedes Gespräch, das ich führe, endet mit der gleichen Frage, die nicht beantwortet wird... lassen Sie mich das klarstellen:

Im Allgemeinen (von der Art, wie Java entwickelt wurde),

  • Error ist für Dinge gedacht, die man niemals einfangen sollte (VM hat eine Erdnussallergie und jemand hat ein Glas Erdnüsse auf ihn fallen lassen)
  • RuntimeException ist für Dinge, die der Programmierer falsch gemacht hat (Programmierer ist über das Ende eines Arrays hinausgegangen)
  • Exception (außer RuntimeException ) ist für Dinge gedacht, die sich der Kontrolle des Programmierers entziehen (die Festplatte füllt sich beim Schreiben in das Dateisystem, das Limit für Dateihandles für den Prozess wurde erreicht und Sie können keine weiteren Dateien öffnen).
  • Throwable ist einfach der übergeordnete Typ für alle Ausnahmetypen.

Ein häufiges Argument, das ich höre, ist, dass, wenn eine Ausnahme auftritt, der Entwickler nur das Programm beenden muss.

Ein weiteres Argument, das ich häufig höre, ist, dass geprüfte Ausnahmen das Refactoring von Code erschweren.

Zu dem Argument "alles, was ich tun werde, ist, das Programm zu beenden" sage ich, dass Sie, selbst wenn Sie es beenden, eine vernünftige Fehlermeldung anzeigen müssen. Wenn Sie sich mit der Behandlung von Fehlern begnügen, werden Ihre Benutzer nicht sehr erfreut sein, wenn das Programm ohne eine klare Angabe des Grundes beendet wird.

Für die Leute, die meinen, dass dies das Refactoring erschwert, bedeutet dies, dass nicht die richtige Abstraktionsebene gewählt wurde. Anstatt eine Methode zu deklarieren, die ein IOException El IOException sollte in eine Ausnahme umgewandelt werden, die dem Geschehen besser entspricht.

Ich habe kein Problem damit, Main mit catch(Exception) (oder in einigen Fällen catch(Throwable) um sicherzustellen, dass das Programm ordnungsgemäß beendet werden kann - aber ich fange immer die spezifischen Ausnahmen ab, die ich benötige. Auf diese Weise kann ich zumindest eine entsprechende Fehlermeldung ausgeben.

Die Frage, die nie beantwortet wird, ist diese:

Wenn Sie werfen RuntimeException Unterklassen anstelle von Exception Unterklassen, wie können Sie dann wissen, was Sie fangen sollen?

Wenn die Antwort "fangen" lautet Exception dann gehen Sie auch mit Programmierfehlern genauso um wie mit Systemausnahmen. Das halte ich für falsch.

Wenn Sie sich Throwable dann behandeln Sie Systemausnahmen und VM-Fehler (und Ähnliches) auf die gleiche Weise. Das halte ich für falsch.

Wenn die Antwort lautet, dass Sie nur die Ausnahmen abfangen, von denen Sie wissen, dass sie ausgelöst werden, wie können Sie dann wissen, welche Ausnahmen ausgelöst werden? Was passiert, wenn Programmierer X eine neue Ausnahme auslöst und vergessen hat, sie abzufangen? Das erscheint mir sehr gefährlich.

Ich würde sagen, dass ein Programm, das einen Stack-Trace anzeigt, falsch ist. Empfinden Leute, die keine geprüften Ausnahmen mögen, das nicht auch so?

Wenn Sie also keine geprüften Ausnahmen mögen, können Sie bitte erklären, warum nicht UND die Frage beantworten, die nicht beantwortet wird?

Ich bin nicht auf der Suche nach Ratschlägen, wann ich eines der beiden Modelle verwenden sollte, sondern nach folgenden Informationen warum Menschen erstrecken sich von RuntimeException weil sie sich nicht gerne von Exception und/oder warum sie eine Ausnahme abfangen und dann eine RuntimeException statt ihre Methode mit Überwürfen zu versehen. Ich möchte die Gründe für die Abneigung gegen geprüfte Ausnahmen verstehen.

1voto

Mister Smith Punkte 25957

Obwohl ich die ganze Seite gelesen habe, kann ich immer noch kein einziges vernünftiges Argument gegen geprüfte Ausnahmen finden. Die meisten Leute sprechen stattdessen über schlechtes API-Design, entweder bei einigen Java-Klassen oder bei ihren eigenen Klassen.

Das einzige Szenario, in dem diese Funktion störend sein kann, ist das Prototiping. Dies könnte durch das Hinzufügen eines Mechanismus in die Sprache gelöst werden (z.B. durch eine @suprescheckedexceptions-Annotation). Aber für die normale Programmierung halte ich geprüfte Ausnahmen für eine gute Sache.

1voto

Jacob Toronto Punkte 11

Wir haben einige Hinweise auf den Chefarchitekten von C# gesehen.

Hier ist ein alternativer Standpunkt von einem Java-Mann darüber, wann geprüfte Ausnahmen verwendet werden sollten. Er räumt viele der von anderen erwähnten Nachteile ein: Wirksame Ausnahmen

0voto

adrian.tarau Punkte 3085

Ich habe viel über die Behandlung von Ausnahmen gelesen, auch wenn ich (meistens) nicht wirklich sagen kann, dass ich glücklich oder traurig über die Existenz von geprüften Ausnahmen bin, ist dies meine Meinung: geprüfte Ausnahmen in Low-Level-Code (IO, Netzwerk, OS, etc.) und ungeprüfte Ausnahmen in High-Level-APIs/Anwendungsebene.

Auch wenn es nicht so einfach ist, eine Grenze zwischen ihnen zu ziehen, finde ich, dass es wirklich ärgerlich/schwierig ist, mehrere APIs/Bibliotheken unter demselben Dach zu integrieren, ohne ständig viele geprüfte Ausnahmen abzufangen, aber andererseits ist es manchmal nützlich/besser, gezwungen zu sein, eine Ausnahme abzufangen und eine andere bereitzustellen, die im aktuellen Kontext mehr Sinn macht.

Das Projekt, an dem ich arbeite, nimmt viele Bibliotheken und integriert sie unter der gleichen API, einer API, die vollständig auf ungeprüften Ausnahmen basiert. Dieses Framework bietet eine High-Level-API, die am Anfang voll von geprüften Ausnahmen war und nur einige ungeprüfte Ausnahmen hatte (Initialisierungsausnahme, ConfigurationException, etc.) und ich muss sagen, war nicht sehr freundlich . Die meiste Zeit mussten Sie Ausnahmen abfangen oder erneut auslösen, von denen Sie nicht wissen, wie sie zu behandeln sind, oder es ist Ihnen sogar egal (nicht zu verwechseln mit Ausnahmen ignorieren), insbesondere auf der Client-Seite, wo ein einziger Klick 10 mögliche (überprüfte) Ausnahmen auslösen kann.

Die aktuelle Version (3. Version) verwendet nur ungeprüfte Ausnahmen und hat einen globalen Ausnahmebehandler, der für die Behandlung aller nicht abgefangenen Ausnahmen zuständig ist. Die API bietet eine Möglichkeit, Exception-Handler zu registrieren, die entscheiden, ob eine Exception als Fehler angesehen wird (meistens ist das der Fall), was bedeutet, dass sie protokolliert und jemand benachrichtigt wird, oder ob sie etwas anderes bedeutet - wie diese Exception, AbortException, was bedeutet, dass der aktuelle Ausführungsthread abgebrochen wird und kein Fehler protokolliert wird, weil es nicht gewünscht ist. Um zu funktionieren, müssen natürlich alle benutzerdefinierten Threads die run()-Methode mit einem try {...} catch(all) behandeln.

public void run() {

try {
     ... do something ...
} catch (Throwable throwable) {
     ApplicationContext.getExceptionService().handleException("Handle this exception", throwable);
}

}

Dies ist nicht notwendig, wenn Sie den WorkerService zur Planung von Aufträgen verwenden (Runnable, Callable, Worker), der alles für Sie erledigt.

Natürlich ist dies nur meine Meinung, und sie mag nicht die richtige sein, aber ich halte sie für einen guten Ansatz. Ich werde sehen, nachdem ich das Projekt veröffentlicht habe, ob das, was ich denke, dass es für mich gut ist, auch für andere gut ist... :)

0voto

finnw Punkte 46519

Aquí ist ein Argument gegen geprüfte Ausnahmen (von joelonsoftware.com):

Der Grund dafür ist, dass ich Ausnahmen für nicht besser halte als "goto's", die seit den 1960er Jahren als schädlich gelten, da sie eine abrupter Sprung von einem Punkt des Codes zu einem anderen. In der Tat sind sie deutlich schlechter als goto's:

  • Sie sind im Quellcode nicht sichtbar. Wenn man sich einen Code-Block ansieht, der Funktionen enthält, die Ausnahmen auslösen können oder nicht, gibt es keine Es gibt keine Möglichkeit zu erkennen, welche Ausnahmen ausgelöst werden könnten und woher sie kommen. Das bedeutet dass selbst eine sorgfältige Code-Inspektion keine potenziellen Fehler aufdeckt.
  • Sie schaffen zu viele mögliche Ausstiegspunkte für eine Funktion. Um korrekten Code zu schreiben, müssen Sie wirklich über jeden möglichen Codepfad durch Ihre Funktion. Jedes Mal, wenn Sie eine Funktion aufrufen, die eine Ausnahme auslösen kann und diese nicht auf der Stelle abfängt, schaffen Sie Möglichkeiten für Überraschungsfehlern, die durch Funktionen verursacht werden, die abrupt beendet werden und Daten in einem inkonsistenten Zustand hinterlassen, oder andere Codepfade, die Sie nicht nicht bedacht haben.

-2voto

Rudi Punkte 23

Meiner Meinung nach sind die geprüften Ausnahmen ein sehr gutes Konzept. Leider haben die meisten Programmierer, die mit mir zusammengearbeitet haben, eine andere Meinung, so dass die Projekte eine Menge falsch verwendeter Ausnahmebehandlungen haben. Ich habe gesehen, dass die meisten Programmierer eine (nur eine) Ausnahmeklasse erstellen, eine Unterklasse von RuntimeException. Diese enthält eine Nachricht, manchmal einen mehrsprachigen Schlüssel. Ich habe keine Möglichkeit, dagegen zu argumentieren. Ich habe den Eindruck, dass ich gegen eine Wand rede, wenn ich ihnen erkläre, was Anti-Patterns sind, was Verträge von Methoden sind... Ich bin ein bisschen enttäuscht.

Aber heute ist klar geworden, dass das Konzept, eine allgemeine Laufzeitausnahme für alles zu haben, ein Anti-Muster ist. Sie haben es für eine Überprüfung einer Benutzereingabe verwendet. Die Ausnahme wird ausgelöst, damit ein Benutzerdialog daraus eine Fehlermeldung machen kann. Aber nicht jeder Aufrufer der Methode ist ein Dialog! Durch das Auslösen der Laufzeit-Exception wurde der Vertrag der Methode geändert, aber nicht deklariert, da es sich nicht um eine geprüfte Exception handelte.

Hoffentlich haben sie heute etwas gelernt und werden ihre Prüfungen (die nützlich und notwendig sind) an einer anderen Stelle durchführen. Nur eine geprüfte Ausnahme zu verwenden, könnte das Problem nicht lösen, aber die geprüfte Ausnahme würde dem Programmierer signalisieren, dass er etwas falsch implementiert.

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