Ich erstelle eine API, eine Funktion, die eine Datei hochlädt. Diese Funktion gibt nichts / nichtig zurück, wenn die Datei korrekt hochgeladen wurde und löst eine Ausnahme aus, wenn ein Problem aufgetreten ist.
Warum eine Ausnahme und nicht nur falsch? Weil ich in einer Ausnahme den Grund für den Fehler angeben kann (keine Verbindung, fehlender Dateiname, falsches Passwort, fehlende Dateibeschreibung usw.). Ich wollte eine benutzerdefinierte Ausnahme erstellen (mit einigen Aufzählungen, um dem API-Benutzer zu helfen, alle Fehler zu behandeln).
Handelt es sich um eine bewährte Methode oder ist es besser, ein Objekt zurückzugeben (mit einem Booleschen Wert im Inneren, einer optionalen Fehlermeldung und der Aufzählung der Fehler)?
java
api-design
exceptions
functions
architectural-patterns
Accollativo
quelle
quelle
Result<T, E>
woT
das Ergebnis ist, wenn es erfolgreich ist, undE
ist der Fehler, wenn es nicht erfolgreich ist. Das Auslösen einer Ausnahme (kann in Java nicht so sicher sein) kann teuer sein, da der Aufrufstapel aufgelöst werden muss, das Erstellen eines Ausnahmeobjekts jedoch kostengünstig ist. Halten Sie sich natürlich an die festgelegten Muster der von Ihnen verwendeten Sprache, aber kombinieren Sie keine Booleschen Werte und Ausnahmen wie diese.fillInStackTrace();
heißt im Superkonstruktor, in der KlasseThrowable
Antworten:
Das Auslösen einer Ausnahme ist lediglich eine zusätzliche Möglichkeit, eine Methode einen Wert zurückgeben zu lassen. Der Aufrufer kann genauso einfach nach einem Rückgabewert suchen wie eine Ausnahme abfangen und dies überprüfen. Die Entscheidung zwischen
throw
undreturn
erfordert daher andere Kriterien.Das Auslösen von Ausnahmen sollte häufig vermieden werden, wenn dadurch die Effizienz Ihres Programms gefährdet wird (das Erstellen eines Ausnahmeobjekts und das Auflösen des Aufrufstapels ist für den Computer viel mehr Arbeit, als nur einen Wert darauf zu schreiben). Wenn der Zweck Ihrer Methode jedoch darin besteht, eine Datei hochzuladen, liegt der Engpass immer bei der Netzwerk- und Dateisystem-E / A. Daher ist es sinnlos, die Rückgabemethode zu optimieren.
Es ist auch eine schlechte Idee, Ausnahmen für einen einfachen Kontrollfluss auszulösen (z. B. wenn eine Suche erfolgreich ist, indem ihr Wert ermittelt wird), da dies die Erwartungen der API-Benutzer verletzt. Aber eine Methode, die ihren Zweck nicht erfüllt, ist ein Ausnahmefall (oder sollte es zumindest sein), daher sehe ich keinen Grund, keine Ausnahme auszulösen. Und wenn Sie das tun, können Sie es genauso gut zu einer benutzerdefinierten, informativeren Ausnahme machen (aber es ist eine gute Idee, es zu einer Unterklasse einer standardmäßigen, allgemeineren Ausnahme wie zu machen
IOException
).quelle
Es gibt absolut keinen Grund,
true
bei Erfolg zurückzukehren, wenn Sie nichtfalse
bei Misserfolg zurückkehren. Wie soll der Client-Code aussehen?In diesem Fall braucht der Aufrufer sowieso einen Try-Catch-Block, aber dann kann er besser schreiben:
Der
true
Rückgabewert ist also für den Aufrufer völlig irrelevant. Behalten Sie also einfach die Methode beivoid
.Im Allgemeinen gibt es drei Möglichkeiten zum Entwerfen von Fehlermodi.
void
die (aktivierte) Ausnahme, werfen Sie sieRückgabe
true
/false
Dies wird in einigen älteren, meist C-artigen APIs verwendet. Die Nachteile liegen auf der Hand, Sie haben keine Ahnung, was schief gelaufen ist. PHP macht das ziemlich oft, was zu folgendem Code führt:
In Multithreading-Kontexten ist dies sogar noch schlimmer.
Wirf (aktivierte) Ausnahmen
Dies ist ein guter Weg, um es zu tun. An einigen Stellen können Sie mit einem Ausfall rechnen. Java macht das mit Sockets. Die Grundannahme ist, dass ein Aufruf erfolgreich sein sollte, aber jeder weiß, dass bestimmte Vorgänge möglicherweise fehlschlagen. Steckdosenanschlüsse gehören dazu. Der Anrufer wird also gezwungen, den Fehler zu behandeln. Es ist ein ansprechendes Design, da es sicherstellt, dass der Anrufer den Fehler tatsächlich behandelt, und dem Anrufer eine elegante Möglichkeit bietet, mit dem Fehler umzugehen.
Ergebnisobjekt zurückgeben
Dies ist eine weitere gute Möglichkeit, damit umzugehen. Es wird oft zum Parsen oder einfach für Dinge verwendet, die validiert werden müssen.
Nette, saubere Logik auch für den Anrufer.
Es gibt einige Debatten darüber, wann der zweite und wann der dritte Fall zu verwenden ist. Einige Leute glauben , dass Ausnahmen sollten außergewöhnliche und dass Sie nicht mit der Möglichkeit von Ausnahmen im Auge entwerfen sollten, und werden so ziemlich immer die dritten Optionen. Das ist in Ordnung. Wir haben jedoch Ausnahmen in Java überprüft, sodass ich keinen Grund sehe, sie nicht zu verwenden. Ich verwende geprüfte Expetitionen, wenn die Grundannahme ist, dass der Aufruf erfolgreich sein sollte (wie das Verwenden eines Sockets), aber ein Fehler möglich ist, und ich verwende die dritte Option, wenn sehr unklar ist, ob der Aufruf erfolgreich sein sollte (wie das Validieren von Daten). Aber dazu gibt es unterschiedliche Meinungen.
In deinem Fall würde ich mit
void
+ gehenException
. Sie erwarten, dass der Dateiupload erfolgreich ist, und wenn dies nicht der Fall ist, ist dies außergewöhnlich. Der Aufrufer ist jedoch gezwungen, diesen Fehlermodus zu verarbeiten, und Sie können eine Ausnahme zurückgeben, die genau beschreibt, welche Art von Fehler aufgetreten ist.quelle
Dies hängt wirklich davon ab, ob ein Fehler außergewöhnlich ist oder erwartet wird .
Wenn ein Fehler normalerweise nicht erwartet wird, ruft der API-Benutzer wahrscheinlich nur Ihre Methode ohne spezielle Fehlerbehandlung auf. Durch das Auslösen einer Ausnahme kann der Stapel an eine Stelle gesprudelt werden, an der er bemerkt wird.
Wenn andererseits Fehler an der Tagesordnung sind, sollten Sie für den Entwickler optimieren, der nach ihnen
try-catch
sucht , und Klauseln sind etwas umständlicher als einif/elif
oder eineswitch
Reihe.Entwerfen Sie eine API immer im Denken einer Person, die sie verwendet.
quelle
Geben Sie keinen Booleschen Wert zurück, wenn Sie nie die Absicht haben, zurückzukehren
false
. Machen Sie einfach die Methodevoid
und dokumentieren Sie, dass sie bei einemIOException
Fehler eine Ausnahme auslöst ( geeignet ist).Der Grund dafür ist, dass der Benutzer Ihrer API, wenn Sie einen Booleschen Wert zurückgeben, möglicherweise zu dem Schluss kommt, dass er dies tun kann:
Das wird natürlich nicht funktionieren; Das heißt, es besteht eine Inkongruenz zwischen dem Vertrag Ihrer Methode und ihrem Verhalten. Wenn Sie eine aktivierte Ausnahme auslösen, muss der Benutzer der Methode den Fehler behandeln:
quelle
Wenn Ihre Methode einen Rückgabewert hat, kann das Auslösen einer Ausnahme die Benutzer überraschen. Wenn ich sehe, dass eine Methode einen Booleschen Wert zurückgibt, bin ich ziemlich davon überzeugt, dass sie true zurückgibt, wenn dies erfolgreich ist, und false, wenn dies nicht der Fall ist, und strukturiere meinen Code mithilfe einer if-else-Klausel. Wenn Ihre Ausnahme ohnehin auf einer Aufzählung basiert, können Sie stattdessen auch einen Aufzählungswert zurückgeben, der Windows HResults ähnelt, und einen Aufzählungswert beibehalten, wenn die Methode erfolgreich ist.
Es ist auch ärgerlich, wenn eine Methode eine Ausnahme auslöst, wenn dies nicht der letzte Schritt in einer Prozedur ist. Das Schreiben eines Try-Catch- und Divert-Kontrollflusses in den Catch-Block ist ein gutes Rezept für Spaghetti und sollte vermieden werden.
Wenn Sie mit Ausnahmen fortfahren, versuchen Sie stattdessen, void zurückzugeben. Benutzer werden feststellen, ob dies erfolgreich ist, wenn keine Ausnahmen ausgelöst werden, und keiner wird versuchen, eine if-else-Klausel zu verwenden, um den Kontrollfluss umzuleiten.
quelle