Defensive Programmierung: Richtlinien in Java

8

Ich komme aus einem .NET-Hintergrund und arbeite jetzt in Java.

Gegenwärtig habe ich große Probleme, eine API defensiv gegen fehlerhafte Eingaben zu entwickeln. Sagen wir, ich habe den folgenden Code (nahe genug):

%Vor%

Dieser Code kann jedoch aus zwei Gründen fehlschlagen:

  1. Der Benutzer übergibt einen null -Knoten.
  2. Der Benutzer übergibt einen ungültigen Knoten, d. h. einen, der nicht im Graphen enthalten ist.

In .NET würde ich ein ArgumentNullException (eher als ein NullReferenceException !) oder ein ArgumentException bzw. übergibt den Namen des problematischen Arguments ( node ) als string Argument.

Java scheint keine entsprechenden Ausnahmen zu haben. Ich erkenne, dass ich spezifischer sein könnte und nur die Ausnahme schreibe, die der Situation am nächsten kommt, oder sogar meine eigene Ausnahmeklasse für die spezifische Situation schreibe.

Ist das die beste Praxis? Oder gibt es universelle Klassen, die in .NET mit ArgumentException vergleichbar sind?

Ist es in diesem Fall sogar sinnvoll, gegen null zu prüfen? Der Code wird trotzdem fehlschlagen und der Stack-Trace der Ausnahme enthält den obigen Methodenaufruf. Die Überprüfung gegen null erscheint redundant und übermäßig. Zugegeben, der Stack-Trace wird etwas sauberer sein (da sein Ziel die obige Methode ist, anstatt eine interne Prüfung in der HashMap -Implementierung der JRE). Dies muss jedoch mit den Kosten einer zusätzlichen if -Anweisung verrechnet werden, die darüber hinaus nie auftreten sollte - schließlich ist die Weitergabe von null an die obige Methode keine erwartete Situation, Es ist ein ziemlich dummer Bug. Erwartet, dass es geradezu paranoid ist - und es wird mit der gleichen Ausnahme scheitern, selbst wenn ich nicht danach suche.

[Wie bereits in den Kommentaren erwähnt, erlaubt HashMap.put tatsächlich null -Werte für den Schlüssel. Also wäre ein Check gegen null hier nicht unbedingt überflüssig.]

    
Konrad Rudolph 18.09.2009, 12:44
quelle

10 Antworten

7

Verschiedene Gruppen haben unterschiedliche Standards.

Erstens, ich nehme an, Sie kennen den Unterschied zwischen RuntimeException s (nicht markiert) und normal Exception s (markiert), wenn nicht, dann sehen Sie diese Frage und die Antworten . Wenn Sie Ihre eigene Ausnahme schreiben, können Sie sie erzwingen, während beide NullPointerException und IllegalArgumentException RuntimeExceptions sind, die in einigen Kreisen verpönt sind.

Zweitens, wie bei Ihnen, haben Gruppen, mit denen ich gearbeitet habe, aber nicht aktiv Behauptungen, aber wenn Ihr Team (oder Verbraucher der API) entschieden hat, dass es Behauptungen verwendet, klingt Assert genau wie der richtige Mechanismus.

Wenn ich du wäre, würde ich NullPointerException verwenden. Der Grund dafür ist Präzedenzfall. Nehmen Sie ein Java-API-Beispiel von Sun, zum Beispiel java.util.TreeSet . Dies verwendet NPEs für genau diese Art von Situation, und während es so aussieht, als ob Ihr Code nur eine Null verwendet, ist es völlig angemessen.

Wie andere gesagt haben, ist IllegalArgumentException eine Option, aber ich denke, dass NullPointerException kommunikativer ist.

Wenn diese API für externe Firmen / Teams gedacht ist, würde ich bei NullPointerException bleiben, aber stelle sicher, dass sie im Javadoc deklariert ist. Wenn es für den internen Gebrauch ist, dann könnten Sie entscheiden, dass das Hinzufügen Ihrer eigenen Exception-Hierarchie lohnenswert ist, aber ich persönlich finde, dass APIs, die riesige Ausnahme-Hierarchien hinzufügen, die nur printStackTrace() d sind oder protokolliert werden, nur eine Verschwendung von Aufwand sind.

Am Ende des Tages ist die Hauptsache, dass Ihr Code klar kommuniziert. Eine lokale Ausnahme-Hierarchie ist wie ein lokaler Jargon - sie fügt Informationen für Insider hinzu, kann aber Außenstehende verblüffen.

Was die Überprüfung gegen null betrifft, würde ich argumentieren, dass es Sinn macht. Erstens können Sie eine Nachricht über das, was Null war (dh Knoten oder Token) hinzufügen, wenn Sie die Ausnahme konstruieren, die hilfreich wäre. Zweitens könnten Sie in Zukunft eine Map -Implementierung verwenden, die null zulässt, und dann würden Sie die Fehlerprüfung verlieren. Die Kosten sind fast nichts. Wenn ein Profiler also nicht sagt, dass es ein Problem mit der inneren Schleife ist, würde ich mir keine Sorgen machen.

    
Nick Fortescue 18.09.2009, 13:28
quelle
12

Die standardmäßige Java-Ausnahme ist IllegalArgumentException . Einige werden NullPointerException ausgeben, wenn das Argument null ist, aber für mich hat NPE die Konnotation "jemand vermasselt", und Sie möchten nicht, dass Clients Ihrer API denken, dass Sie nicht wissen, was Sie tun.

Überprüfen Sie bei öffentlichen APIs die Argumente und schlagen Sie früh und sauber fehl. Die Zeit / Kosten spielen kaum eine Rolle.

    
Ken 18.09.2009 12:49
quelle
7

In Java würden Sie normalerweise eine IllegalArgumentException

auslösen     
Fortyrunner 18.09.2009 12:46
quelle
2

Wenn Sie einen Leitfaden zum Schreiben von gutem Java-Code benötigen, kann ich das Buch Effektives Java wärmstens empfehlen > von Joshua Bloch.

    
Jesper 18.09.2009 12:49
quelle
2

Es scheint, dass dies eine angemessene Verwendung für eine Bestätigung :

%Vor%     
Greg Hewgill 18.09.2009 12:52
quelle
2

Ihr Ansatz hängt ganz davon ab, welchen Vertrag Ihre Funktion den Anrufern anbietet - ist es eine Voraussetzung, dass der Knoten nicht null ist?

Wenn dies der Fall ist, sollten Sie eine Ausnahme auslösen, wenn der Knoten null ist, da es sich um eine Vertragsverletzung handelt. Wenn dies nicht der Fall ist, sollte Ihre Funktion den Null-Knoten automatisch behandeln und entsprechend antworten.

    
PaulJWilliams 18.09.2009 12:48
quelle
1

Ich denke viel hängt vom Vertrag der Methode ab und wie gut der Anrufer bekannt ist.

An einem bestimmten Punkt des Prozesses konnte der Aufrufer Maßnahmen ergreifen, um den Knoten vor dem Aufruf der Methode zu validieren. Wenn Sie den Anrufer kennen und wissen, dass diese Knoten immer validiert sind, denke ich, dass es in Ordnung ist anzunehmen, dass Sie gute Daten erhalten. Im Wesentlichen liegt die Verantwortung beim Anrufer.

Wenn Sie jedoch zum Beispiel eine Bibliothek eines Drittanbieters bereitstellen, die verteilt wird, müssen Sie den Knoten auf Nullen, Etcs ... validieren.

Eine illegalArugementException ist der Java-Standard, ist aber auch eine RunTimeException. Wenn Sie also den Aufrufer zwingen möchten, die Ausnahme zu behandeln, müssen Sie eine Prüfausnahme bereitstellen, wahrscheinlich eine benutzerdefinierte, die Sie erstellen.

    
richs 18.09.2009 13:34
quelle
1

Ich persönlich möchte, dass NullPointerExceptions NUR zufällig auftreten, also muss etwas anderes verwendet werden, um anzuzeigen, dass ein ungültiger Argumentwert übergeben wurde. IllegalArgumentException ist dafür geeignet.

%Vor%

Dies sollte sowohl für diejenigen, die den Code lesen, als auch für die arme Seele, die um 3 Uhr morgens einen Unterstützungsruf bekommt, ausreichen.

(und, geben Sie IMMER einen erklärenden Text für Ihre Ausnahmen, Sie schätzen sie einen traurigen Tag)

    
quelle
0

wie der andere: java.lang.IllegalArgumentException. Fragen Sie beim Überprüfen von "null Node", wie Sie fehlerhafte Eingaben bei der Node-Erstellung überprüfen?

    
Antoine Claval 18.09.2009 12:51
quelle
0

Ich muss niemanden zufrieden stellen, also was ich jetzt als kanonischen Code mache, ist

%Vor%

was mir viel Schlaf bringt.

Andere werden nicht zustimmen.

    
Nicholas Jordan 12.10.2009 04:18
quelle