Ich habe eine Funktion geschrieben, die einen Benutzer zur Eingabe auffordert, bis der Benutzer eine positive Ganzzahl (eine natürliche Zahl) eingibt. Jemand sagte, ich sollte keine Ausnahmen in meiner Funktion auslösen und abfangen und den Aufrufer meiner Funktion damit umgehen lassen.
Ich frage mich, was andere Entwickler darüber denken. Ich missbrauche wahrscheinlich auch Ausnahmen in der Funktion. Hier ist der Code in Java:
private static int sideInput()
{
int side = 0;
String input;
Scanner scanner = new Scanner(System.in);
do {
System.out.print("Side length: ");
input = scanner.nextLine();
try {
side = Integer.parseInt(input);
if (side <= 0) {
// probably a misuse of exceptions
throw new NumberFormatException();
}
}
catch (NumberFormatException numFormExc) {
System.out.println("Invalid input. Enter a natural number.");
}
} while (side <= 0);
return side;
}
Ich interessiere mich für zwei Dinge:
- Sollte ich den Anrufer über Ausnahmen sorgen lassen? Der Punkt der Funktion ist, dass sie den Benutzer nervt, bis der Benutzer eine natürliche Zahl eingibt. Ist der Punkt der Funktion schlecht? Ich spreche nicht von der Benutzeroberfläche (Benutzer kann ohne ordnungsgemäße Eingabe nicht aus der Schleife herauskommen), sondern von Schleifeneingaben mit Ausnahmen.
- Würden Sie sagen, dass die throw-Anweisung (in diesem Fall) ein Missbrauch von Ausnahmen ist? Ich könnte leicht ein Flag zum Überprüfen der Gültigkeit der Nummer erstellen und die Warnmeldung basierend auf diesem Flag ausgeben. Aber das würde dem Code mehr Zeilen hinzufügen und ich denke, er ist so wie er ist perfekt lesbar.
Die Sache ist, ich schreibe oft eine separate Eingabefunktion. Wenn der Benutzer eine Zahl mehrmals eingeben muss, erstelle ich eine separate Funktion für die Eingabe, die alle Formatierungsausnahmen und -einschränkungen behandelt.
exceptions
usr
quelle
quelle
Antworten:
Der Punkt einer Ausnahme ist, dass eine Methode dem Aufrufer mitteilen kann, der in einen Zustand eingetreten ist, in dem er nicht normal fortgesetzt werden konnte, ohne dass Sie gezwungen sind, einen Fehlercode in den Rückgabewert einzubetten.
In Ihrem Fall weiß Ihre Methode genau, was zu tun ist, wenn die Eingabe nicht größer als 0 ist. Der einzige Grund, warum Sie hier Zeilen speichern, besteht darin, dass Sie zufällig dieselbe Ausnahme auslösen, die Sie erhalten würden, wenn die Eingabe keine Zahl wäre. Die Ausnahme, die Sie auslösen, zeigt jedoch nicht richtig an, warum Ihr Code die Eingabe nicht mag. Wenn jemand anderes mitkommen und diesen Code sehen würde, müsste er zusätzliche Zeit damit verbringen, genau zu sehen, wie die Dinge funktionieren.
quelle
Dies ist eine schlechte Verwendung von Ausnahmen. Zunächst einmal ist eine nicht positive Zahl keine Formatausnahme.
Warum überhaupt Ausnahmen verwenden? Wenn Sie wissen, welche Eingabe nicht zulässig ist, brechen Sie die Schleife erst ab, wenn Sie vom Benutzer eine gültige Eingabe erhalten, etwa wie folgt:
quelle
Integer.parseInt()
löst ein aus,NumberFormatException
wenn das angegebene String-Argument nicht analysiert werden kann. Sie müssen die Ausnahme nicht selbst auslösen (und Sie werden es auch nicht können).Integer.parseInt()
Methode die Ausnahme für Sie auslöst , wenn sie auftritt, können Sie sie danach nicht selbst auslösen, da sie bereits ausgelöst wurde.Ausnahmen nur abfangen, wenn Sie etwas tun möchten, das für den aktuellen Methodenaufruf relevant ist. dh Bereinigung, Fehlerlogik usw. In diesem Fall sendet der Catch lediglich eine Nachricht an die Konsole. Dies ist für die sideInput-Methode nicht relevant, sodass er weiter oben in der Aufrufkette / im Aufrufstapel verarbeitet werden kann.
Man kann das try / catch hier loswerden und einfach den Methodenaufruf dokumentieren:
Diese Ausnahme muss noch weiter oben in der Aufrufkette / im Stack behandelt werden!
quelle
Sie sollten in einer Methode nicht dieselbe Ausnahme auslösen und abfangen. Ich denke sogar, dass der catch-Block dieselbe Ausnahme abfängt, die Sie auslösen, sodass Sie sie nicht wirklich auslösen.
Wenn
parseInt
es erfolgreich war, dann ist es keinNumberFormatException
.Wenn die Seite kleiner als Null ist, sollten Sie a werfen
NegativeSideLengthException
.Erstellen Sie eine benutzerdefinierte / geschäftliche Ausnahme mit dem Namen
NegativeSideLengthException
Dann
sideInput
wirft NegativeSideLengthExceptionSie können sogar (wenn Sie möchten) einen weiteren catch-Block hinzufügen, um ihn zu fangen,
NegativeSideLengthException
ohne dass die Methode ihn wirft.Flags sind keine gute Möglichkeit, mit Ausnahmen umzugehen.
quelle
Ausnahmen sind ziemlich albtraumhafte Dinge, sie bringen mehr Komplexität mit sich als sie lösen.
Erstens, wenn Sie Ihre Ausnahmen nicht abfangen, kann der Anrufer dies nur tun
on error resume next
, dh nach einer Woche wissen selbst Sie nicht, was Ihre Funktion auslösen kann und was Sie damit tun sollen:Grundsätzlich muss man, wenn man sie fängt, ein sehr gutes Verständnis für Verträge und Ausnahmegarantien haben. Das passiert in einer realen Welt selten. Und auch Ihr Code wird schwer zu lesen sein.
Das Lustige ist auch, dass Sie, wenn Sie wirklich die Chance haben, Ausnahmen zu behandeln, eine echte RAII-Sprache benötigen, die irgendwie humorvoll ist, da es bei Java und .NET nur um Ausnahmen geht ...
Wiederholen Sie dies noch einmal, aber ...:
http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
http://www.joelonsoftware.com/items/2003/10/13.html
quelle
: throw(thisexception, thatexception)
sind völlig falsch und sollten niemals verwendet werden, da Sie sonst unerwartet werden, außer.catch
. Ein ignorierter Rückgabewert ist zwar nicht durchsuchbar, kann jedoch nur durch zeilenweise Codeüberprüfung identifiziert werden. Last but not least haben Konstruktoren keine Rückgabewerte. Dies ist der Hauptgrund für die Verwendung von Ausnahmen.