it-swarm.com.de

Mir wurde gesagt, dass Ausnahmen nur in Ausnahmefällen verwendet werden sollten. Woher weiß ich, ob mein Fall außergewöhnlich ist?

Mein spezieller Fall hier ist, dass der Benutzer eine Zeichenfolge an die Anwendung übergeben kann, die Anwendung sie analysiert und strukturierten Objekten zuweist. Manchmal kann der Benutzer etwas Ungültiges eingeben. Zum Beispiel kann ihre Eingabe eine Person beschreiben, aber sie können sagen, dass ihr Alter "Apple" ist. In diesem Fall ist es korrekt, die Transaktion zurückzusetzen und dem Benutzer mitzuteilen, dass ein Fehler aufgetreten ist, und er muss es erneut versuchen. Möglicherweise muss jeder Fehler gemeldet werden, den wir in der Eingabe finden, nicht nur der erste.

In diesem Fall habe ich argumentiert, wir sollten eine Ausnahme auslösen. Er war anderer Meinung und sagte: "Ausnahmen sollten außergewöhnlich sein: Es wird erwartet, dass der Benutzer ungültige Daten eingibt, daher ist dies kein Ausnahmefall." Ich wusste nicht wirklich, wie ich diesen Punkt argumentieren sollte, weil er per Definition des Wortes scheint richtig zu sein.

Ich verstehe jedoch, dass aus diesem Grund Ausnahmen erfunden wurden. Früher waren Sie had, um das Ergebnis zu überprüfen, um festzustellen, ob ein Fehler aufgetreten ist. Wenn Sie dies nicht überprüfen, können schlimme Dinge passieren, ohne dass Sie es merken.

Ohne Ausnahmen muss jede Ebene des Stapels das Ergebnis der von ihnen aufgerufenen Methoden überprüfen. Wenn ein Programmierer vergisst, eine dieser Ebenen einzuchecken, kann der Code versehentlich fortfahren und ungültige Daten speichern (zum Beispiel). Scheint auf diese Weise fehleranfälliger zu sein.

Wie auch immer, zögern Sie nicht, alles zu korrigieren, was ich hier gesagt habe. Meine Hauptfrage ist, ob jemand sagt, Ausnahmen sollten außergewöhnlich sein. Woher weiß ich, ob mein Fall außergewöhnlich ist?

102
Daniel Kaplan

Ausnahmen wurden erfunden, um die Fehlerbehandlung mit weniger Code-Unordnung zu vereinfachen. Sie sollten sie in Fällen verwenden, in denen sie die Fehlerbehandlung mit weniger Code-Unordnung vereinfachen. Dieses Geschäft "Ausnahmen nur für außergewöhnliche Umstände" stammt aus einer Zeit, in der die Ausnahmebehandlung als inakzeptabler Leistungseinbruch eingestuft wurde. Dies ist in der überwiegenden Mehrheit des Codes nicht mehr der Fall, aber die Leute sprechen die Regel immer noch aus, ohne sich an den Grund dafür zu erinnern.

Besonders in Java, der vielleicht außergewöhnlichsten Sprache, die jemals entwickelt wurde, sollten Sie sich nicht schlecht fühlen, wenn Sie Ausnahmen verwenden wenn dies Ihren Code vereinfacht. Tatsächlich Javas eigene Integer -Klasse hat keine Möglichkeit zu überprüfen, ob eine Zeichenfolge eine gültige Ganzzahl ist, ohne möglicherweise ein NumberFormatException auszulösen.

Auch wenn Sie sich nicht nur auf die Validierung der Benutzeroberfläche verlassen können, sollten Sie berücksichtigen, ob Ihre Benutzeroberfläche ordnungsgemäß entworfen wurde, z. B. die Verwendung eines Drehfelds zur Eingabe kurzer Zahlen Werte, dann wäre ein nicht numerischer Wert, der es wirklich ins Backend schafft, eine außergewöhnliche Bedingung.

88
Karl Bielefeldt

Wann sollte eine Ausnahme ausgelöst werden? Wenn es um Code geht, halte ich die folgende Erklärung für sehr hilfreich:

Eine Ausnahme ist, wenn ein Mitglied die Aufgabe, die es ausführen soll, nicht wie durch seinen Namen angegeben ausführt. (Jeffry Richter, CLR über C #)

Warum ist es hilfreich? Es deutet darauf hin, dass es vom Kontext abhängt, wann etwas als Ausnahme behandelt werden soll oder nicht. Auf der Ebene der Methodenaufrufe wird der Kontext durch (a) den Namen, (b) die Signatur der Methode und (b) den Clientcode angegeben, der die Methode verwendet oder voraussichtlich verwenden wird.

Um Ihre Frage zu beantworten, sollten Sie sich den Code ansehen, in dem Benutzereingaben verarbeitet werden. Es könnte ungefähr so ​​aussehen:

public void Save(PersonData personData) { … }

Schlägt der Methodenname vor, dass eine Validierung durchgeführt wurde? Nein. In diesem Fall sollte eine ungültige PersonData eine Ausnahme auslösen.

Angenommen, die Klasse verfügt über eine andere Methode, die folgendermaßen aussieht:

public ValidationResult Validate(PersonData personData) { … }

Schlägt der Methodenname vor, dass eine Validierung durchgeführt wurde? Ja. In diesem Fall sollte eine ungültige PersonData keine Ausnahme auslösen.

Um die Dinge zusammenzufügen, schlagen beide Methoden vor, dass der Client-Code folgendermaßen aussehen sollte:

ValidationResult validationResult = personRegister.Validate(personData);
if (validationResult.IsValid())
{
    personRegister.Save(personData)
}
else
{
    // Throw an exception? To answer this look at the context!
    // That is: (a) Method name, (b) signature and
    // (c) where this method is (expected) to be used.
}

Wenn nicht klar ist, ob eine Methode eine Ausnahme auslösen soll, liegt dies möglicherweise an einem schlecht ausgewählten Methodennamen oder einer schlecht ausgewählten Signatur. Vielleicht ist das Design der Klasse nicht klar. Manchmal müssen Sie das Code-Design ändern, um eine klare Antwort auf die Frage zu erhalten, ob eine Ausnahme ausgelöst werden soll oder nicht.

72
Theo Lenndorff

Ausnahmen sollten außergewöhnlich sein: Es wird erwartet, dass der Benutzer ungültige Daten eingibt, daher ist dies kein Ausnahmefall

Zu diesem Argument:

  • Es wird erwartet, dass eine Datei möglicherweise nicht vorhanden ist, sodass dies kein Ausnahmefall ist.
  • Es wird erwartet, dass die Verbindung zum Server unterbrochen wird, sodass dies kein Ausnahmefall ist
  • Es wird erwartet, dass die Konfigurationsdatei möglicherweise verstümmelt ist, sodass dies kein Ausnahmefall ist
  • Es wird erwartet, dass Ihre Anfrage manchmal ausfällt, sodass dies kein Ausnahmefall ist

Jede Ausnahme, die Sie fangen, müssen Sie erwarten, weil Sie sich entschieden haben, sie zu fangen. Nach dieser Logik sollten Sie also niemals Ausnahmen auslösen, die Sie tatsächlich abfangen möchten.

Daher denke ich, dass "Ausnahmen außergewöhnlich sein sollten" eine schreckliche Faustregel ist.

Was Sie tun sollten, hängt von der Sprache ab. Verschiedene Sprachen haben unterschiedliche Konventionen darüber, wann Ausnahmen ausgelöst werden sollen. Python zum Beispiel löst Ausnahmen für alles aus und wenn ich in Python bin, folge ich diesem Beispiel. C++ hingegen wirft relativ wenige Ausnahmen auf, und da folge ich dem Beispiel. Sie können C++ oder Java like Python] behandeln und Ausnahmen für alles auslösen, aber Sie arbeiten im Widerspruch dazu, wie die Sprache erwartet, dass sie verwendet wird.

Ich bevorzuge Pythons Ansatz, aber ich halte es für eine schlechte Idee, andere Sprachen darin einzuschleusen.

31
Winston Ewert

Ich denke immer an Dinge wie den Zugriff auf den Datenbankserver oder eine Web-API, wenn ich an Ausnahmen denke. Sie erwarten, dass die Server-/Web-API funktioniert, in Ausnahmefällen jedoch möglicherweise nicht (Server ist ausgefallen). Eine Webanforderung ist normalerweise schnell, kann jedoch in Ausnahmefällen (hohe Auslastung) eine Zeitüberschreitung verursachen. Dies liegt außerhalb Ihrer Kontrolle.

Die Eingabedaten Ihrer Benutzer liegen in Ihrer Kontrolle, da Sie überprüfen können, was sie senden, und damit tun können, was Sie möchten. In Ihrem Fall würde ich die Benutzereingaben überprüfen, bevor ich überhaupt versuche, sie zu speichern. Ich stimme eher zu, dass Benutzer, die ungültige Daten bereitstellen, erwartet werden sollten, und Ihre App sollte dies berücksichtigen, indem sie die Eingabe validiert und die benutzerfreundliche Fehlermeldung bereitstellt.

Trotzdem verwende ich in den meisten meiner Domain-Modell-Setter Ausnahmen, bei denen es absolut unmöglich sein sollte, dass ungültige Daten eingehen. Dies ist jedoch eine letzte Verteidigungslinie, und ich neige dazu, meine Eingabeformulare mit umfangreichen Validierungsregeln zu erstellen , so dass es praktisch keine Chance gibt, diese Domänenmodellausnahme auszulösen. Wenn ein Setter also eine Sache erwartet und eine andere bekommt, ist dies eine Ausnahmesituation, die unter normalen Umständen nicht hätte passieren dürfen.

BEARBEITEN (etwas anderes zu beachten):

Wenn Sie vom Benutzer bereitgestellte Daten an die Datenbank senden, wissen Sie im Voraus, was Sie in Ihre Tabellen eingeben sollten und was nicht. Dies bedeutet, dass Daten anhand eines erwarteten Formats validiert werden können. Dies können Sie steuern. Was Sie nicht kontrollieren können, ist, dass Ihr Server mitten in Ihrer Abfrage ausfällt. Sie wissen also, dass die Abfrage in Ordnung ist und die Daten gefiltert/validiert wurden. Sie versuchen die Abfrage und sie schlägt immer noch fehl. Dies ist eine Ausnahmesituation.

Ähnlich wie bei den Webanfragen können Sie nicht wissen, ob die Anfrage abgelaufen ist oder keine Verbindung hergestellt werden kann, bevor Sie versuchen, sie zu senden. Dies erfordert also auch einen Try/Catch-Ansatz, da Sie den Server nicht fragen können, ob er einige Millisekunden später beim Senden der Anforderung funktioniert.

30
Ivan Pintar

Referenz

Von The Pragmatic Programmer :

Wir glauben, dass Ausnahmen selten als Teil des normalen Ablaufs eines Programms verwendet werden sollten. Ausnahmen sollten für unerwartete Ereignisse reserviert werden. Angenommen, eine nicht erfasste Ausnahme beendet Ihr Programm und fragt sich: "Wird dieser Code weiterhin ausgeführt, wenn ich alle Ausnahmebehandlungsroutinen entferne?" Wenn die Antwort "Nein" lautet, werden möglicherweise Ausnahmen unter nicht außergewöhnlichen Umständen verwendet.

Anschließend untersuchen sie das Beispiel des Öffnens einer Datei zum Lesen, und die Datei existiert nicht - sollte dies eine Ausnahme auslösen?

Wenn die Datei vorhanden sein sollte, ist eine Ausnahme gerechtfertigt. [...] Wenn Sie jedoch keine Ahnung haben, ob die Datei vorhanden sein soll oder nicht, erscheint es nicht außergewöhnlich, wenn Sie sie nicht finden können, und eine Fehlerrückgabe ist angemessen.

Später diskutieren sie, warum sie diesen Ansatz gewählt haben:

Die Ausnahme [A] n stellt eine sofortige, nicht lokale Übertragung der Kontrolle dar - es ist eine Art Kaskadierung goto. Programme, die im Rahmen ihrer normalen Verarbeitung Ausnahmen verwenden, leiden unter allen Lesbarkeits- und Wartbarkeitsproblemen des klassischen Spaghetti-Codes. Diese Programme unterbrechen die Kapselung: Routinen und ihre Anrufer sind über die Ausnahmebehandlung enger miteinander verbunden.

In Bezug auf Ihre Situation

Ihre Frage lautet: "Sollten Validierungsfehler Ausnahmen auslösen?" Die Antwort ist, dass es davon abhängt, wo die Validierung stattfindet.

Befindet sich die betreffende Methode in einem Abschnitt des Codes, in dem angenommen wird, dass die Eingabedaten bereits validiert wurden, sollten ungültige Eingabedaten eine Ausnahme auslösen. Wenn der Code so konzipiert ist, dass diese Methode die genaue Eingabe erhält, die von einem Benutzer eingegeben wurde, sind ungültige Daten zu erwarten, und eine Ausnahme sollte nicht ausgelöst werden.

16
Mike Partridge

Es gibt hier eine Menge philosophischer Pontifikationen, aber im Allgemeinen sind außergewöhnliche Bedingungen einfach jene Bedingungen mit denen Sie nicht umgehen können oder wollen (außer Bereinigung, Fehlerberichterstattung und dergleichen) ohne Benutzereingriff . Mit anderen Worten, es handelt sich um nicht behebbare Zustände.

Wenn Sie einem Programm einen Dateipfad übergeben, um diese Datei auf irgendeine Weise zu verarbeiten, und die durch diesen Pfad angegebene Datei nicht vorhanden ist, ist dies eine Ausnahmebedingung. Sie können in Ihrem Code nichts anderes tun, als ihn dem Benutzer zu melden und ihm zu erlauben, einen anderen Dateipfad anzugeben.

11
Robert Harvey

Es gibt zwei Bedenken, die Sie berücksichtigen sollten:

  1. sie diskutieren ein einzelnes Problem - nennen wir es Assigner, da dieses Problem darin besteht, strukturierten Objekten Eingaben zuzuweisen - und Sie drücken die Einschränkung aus, dass seine Eingaben gültig sind

  2. a gut implementiert Benutzeroberfläche hat ein zusätzliches Problem: Validierung von Benutzereingaben und konstruktives Feedback zu Fehlern (nennen wir diesen Teil Validator)

Aus Sicht der Assigner -Komponente ist das Auslösen einer Ausnahme völlig sinnvoll, da Sie eine Einschränkung ausgedrückt haben, gegen die verstoßen wurde.

Aus Sicht der Benutzererfahrung Sollte der Benutzer überhaupt nicht direkt mit diesem Assigner sprechen. Sie sollten mit ihm sprechen via the Validator.

In Validator ist eine ungültige Benutzereingabe nicht ein Ausnahmefall, es ist wirklich der Fall, an dem Sie mehr interessiert sind. Hier wäre also eine Ausnahme nicht angemessen. und hier möchten Sie auch all Fehler identifizieren, anstatt beim ersten auszusteigen.

Sie werden feststellen, dass ich nicht erwähnt habe, wie diese Bedenken implementiert werden. Es scheint, dass Sie über das Assigner sprechen und Ihr Kollege über ein kombiniertes Validator+Assigner. Sobald Sie feststellen, dass sind zwei getrennte (oder trennbare) Bedenken, können Sie es zumindest vernünftig diskutieren.


Um auf Renans Kommentar einzugehen, bin ich nur vorausgesetzt, dass es offensichtlich ist, welche Fälle in jedem Kontext als außergewöhnlich angesehen werden sollten, sobald Sie Ihre zwei getrennten Bedenken identifiziert haben.

In der Tat, wenn es nicht offensichtlich ist, ob etwas als außergewöhnlich angesehen werden sollte, würde ich argumentieren, dass Sie die unabhängigen Bedenken in Ihrer Lösung wahrscheinlich noch nicht vollständig identifiziert haben.

Ich denke, das ist die direkte Antwort auf

... woher weiß ich, ob mein Fall außergewöhnlich ist?

vereinfache weiter, bis es offensichtlich ist. Wenn Sie einen Stapel einfacher Konzepte haben, die Sie gut verstehen, können Sie klar darüber nachdenken, sie wieder in Code, Klassen, Bibliotheken oder was auch immer zusammenzusetzen.

7
Useless

Andere haben gut geantwortet, aber hier ist noch meine kurze Antwort. Ausnahme ist eine Situation, in der etwas in der Umgebung nicht stimmt, was Sie nicht kontrollieren können und Ihr Code überhaupt nicht vorwärts gehen kann. In diesem Fall müssen Sie den Benutzer auch darüber informieren, was schief gelaufen ist, warum Sie nicht weiter gehen können und wie die Auflösung ist.

4
Manoj R

Ich war noch nie ein großer Fan des Ratschlags, dass Sie Ausnahmen nur in Ausnahmefällen auslösen sollten, zum Teil, weil sie nichts aussagen (es ist wie zu sagen, dass Sie nur essbare Lebensmittel essen sollten), aber auch, weil dies der Fall ist ist sehr subjektiv und es ist oft nicht klar, was einen Ausnahmefall darstellt und was nicht.

Es gibt jedoch gute Gründe für diesen Rat: Das Auslösen und Abfangen von Ausnahmen ist langsam. Wenn Sie Ihren Code im Debugger in Visual Studio ausführen, der Sie benachrichtigt, wenn eine Ausnahme ausgelöst wird, können Sie von Dutzenden Spam erhalten wenn nicht Hunderte von Nachrichten, lange bevor Sie zum Problem kommen.

Also in der Regel, wenn:

  • ihr Code ist fehlerfrei und
  • die Dienste, von denen es abhängt, sind alle verfügbar, und
  • ihr Benutzer verwendet Ihr Programm so, wie es verwendet werden sollte (auch wenn einige der von ihm bereitgestellten Eingaben ungültig sind).

dann sollte Ihr Code niemals eine Ausnahme auslösen, auch nicht eine, die später abgefangen wird. Um ungültige Daten abzufangen, können Sie Validatoren auf UI-Ebene oder Code wie Int32.TryParse() in der Präsentationsebene verwenden.

Für alles andere sollten Sie sich an das Prinzip halten, dass eine Ausnahme bedeutet, dass Ihre Methode nicht das tun kann, was ihr Name sagt. Im Allgemeinen ist dies nicht der Fall Es ist aus zwei Gründen eine gute Idee, Rückkehrcodes zu verwenden, um einen Fehler anzuzeigen (es sei denn, Ihr Methodenname weist eindeutig darauf hin, dass dies der Fall ist, z. B. TryParse()). Erstens besteht die Standardantwort auf einen Fehlercode darin, die Fehlerbedingung zu ignorieren und trotzdem fortzufahren. Zweitens können Sie allzu leicht mit einigen Methoden enden, die Rückkehrcodes verwenden, und mit anderen Methoden, die Ausnahmen verwenden, und vergessen, welche welche ist. Ich habe sogar Codebasen gesehen, bei denen zwei verschiedene austauschbare Implementierungen derselben Schnittstelle hier unterschiedliche Ansätze verfolgen.

3
jammycakes

Möglicherweise muss jeder Fehler gemeldet werden, den wir in der Eingabe finden, nicht nur der erste.

Aus diesem Grund können Sie hier keine Ausnahme auslösen. Eine Ausnahme unterbricht sofort den Validierungsprozess. Es würde also viel Arbeit geben, um dies zu erreichen.

Ein schlechtes Beispiel:

Validierungsmethode für die Klasse Dog mit Ausnahmen:

void validate(Set<DogValidationException> previousExceptions) {
    if (!DOG_NAME_PATTERN.matcher(this.name).matches()) {
        DogValidationException disallowedName = new DogValidationException(Problem.DISALLOWED_DOG_NAME);
        if (!previousExceptions.contains(disallowedName)){
            throw disallowedName;
        }
    }
    if (this.legs < 4) {
        DogValidationException invalidDog = new DogValidationException(Problem.LITERALLY_INVALID_DOG);
        if (!previousExceptions.contains(invalidDog)){
            throw invalidDog;
        }
    }
    // etc.
}

Wie man es nennt:

Set<DogValidationException> exceptions = new HashSet<DogValidationException>();
boolean retry;
do {
    retry = false;
    try {
        dog.validate(exceptions);
    } catch (DogValidationException e) {
        exceptions.add(e);
        retry = true;
    }
} while (retry);

if(exceptions.isEmpty()) {
    dogDAO.beginTransaction();
    dogDAO.save(dog);
    dogDAO.commitAndCloseTransaction();
} else {
    // notify user to fix the problems
}

Das Problem hierbei ist, dass der Validierungsprozess, um alle Fehler zu erhalten, bereits gefundene Ausnahmen überspringen muss. Das obige könnte funktionieren, aber dies ist ein klarer Missbrauch von Ausnahmen. Die Art der Validierung, nach der Sie gefragt wurden, sollte stattfinden , bevor die Datenbank berührt wird. Es ist also nicht erforderlich, etwas zurückzusetzen. Und die Ergebnisse der Validierung sind wahrscheinlich Validierungsfehler (hoffentlich jedoch Null).

Der bessere Ansatz ist:

Methodenaufruf:

Set<Problem> validationResults = dog.validate();
if(validationResults.isEmpty()) {
    dogDAO.beginTransaction();
    dogDAO.save(dog);
    dogDAO.commitAndCloseTransaction();
} else {
    // notify user to fix the problems
}

Validierungsmethode:

Set<Problem> validate() {
    Set<Problem> result = new HashSet<Problem>();
    if(!DOG_NAME_PATTERN.matcher(this.name).matches()) {
        result.add(Problem.DISALLOWED_DOG_NAME);
    }
    if(this.legs < 4) {
        result.add(Problem.LITERALLY_INVALID_DOG);
    }
    // etc.
    return result;
}

Warum? Es gibt unzählige Gründe, und die meisten Gründe wurden in den anderen Antworten genannt. Einfach ausgedrückt: Es ist viel einfacher von anderen zu lesen und zu verstehen. Zweitens möchten Sie die User-Stack-Traces anzeigen, um ihm zu erklären, dass er sein dog falsch eingerichtet hat?

If, während des Commits im zweiten Beispiel, es tritt immer noch ein Fehler auf, obwohl Ihr Validator das dog mit null Problemen validiert hat, dann eine Ausnahme auszulösen ist das Richtige. Gefällt mir: Keine Datenbankverbindung, der Datenbankeintrag wurde inzwischen von einer anderen Person geändert.

2
Matthias Ronge

Ausnahmen sollten Bedingungen darstellen, unter denen es wahrscheinlich ist sofortig Der aufrufende Code ist nicht für die Verarbeitung vorbereitet, selbst wenn die aufrufende Methode dies möglicherweise tut. Angenommen, Code, der einige Daten aus einer Datei liest, kann zu Recht davon ausgehen, dass eine gültige Datei mit einem gültigen Datensatz endet, und ist nicht erforderlich, um Informationen aus einem Teildatensatz zu extrahieren.

Wenn die Lese-Daten-Routine keine Ausnahmen verwendet, sondern lediglich meldet, ob der Lesevorgang erfolgreich war oder nicht, muss der aufrufende Code folgendermaßen aussehen:

temp = dataSource.readInteger();
if (temp == null) return null;
field1 = (int)temp;
temp = dataSource.readInteger();
if (temp == null) return null;
field2 = (int)temp;
temp = dataSource.readString();
if (temp == null) return null;
field3 = temp;

usw. drei Codezeilen für jede nützliche Arbeit ausgeben. Wenn dagegen readInteger beim Auftreten einer Datei eine Ausnahme auslöst und der Aufrufer die Ausnahme einfach weitergeben kann, lautet der Code:

field1 = dataSource.readInteger();
field2 = dataSource.readInteger();
field3 = dataSource.readString();

Viel einfacher und sauberer aussehend, mit weitaus größerem Schwerpunkt auf dem Fall, dass die Dinge normal funktionieren. Beachten Sie, dass in Fällen, in denen der unmittelbare Aufrufer würde erwartet, eine Bedingung zu behandeln, eine Methode, die einen Fehlercode zurückgibt, häufig hilfreicher ist als eine, die eine Ausnahme auslöst. So summieren Sie beispielsweise alle Ganzzahlen in einer Datei:

do
{
  temp = dataSource.tryReadInteger();
  if (temp == null) break;
  total += (int)temp;
} while(true);

versus

try
{
  do
  {
    total += (int)dataSource.readInteger();
  }
  while(true);
}
catch endOfDataSourceException ex
{ // Don't do anything, since this is an expected condition (eventually)
}

Der Code, der nach den ganzen Zahlen fragt, erwartet, dass einer dieser Aufrufe fehlschlägt. Die Verwendung einer Endlosschleife durch den Code, die bis dahin ausgeführt wird, ist weitaus weniger elegant als die Verwendung einer Methode, die Fehler über ihren Rückgabewert anzeigt.

Da Klassen häufig nicht wissen, welche Bedingungen ihre Clients erwarten oder nicht erwarten, ist es oft hilfreich, zwei Versionen von Methoden anzubieten, die auf eine Weise fehlschlagen können, die einige Anrufer erwarten und andere Anrufer nicht. Auf diese Weise können solche Methoden bei beiden Anrufertypen sauber verwendet werden. Beachten Sie auch, dass selbst "try" -Methoden Ausnahmen auslösen sollten, wenn Situationen auftreten, die der Aufrufer wahrscheinlich nicht erwartet. Beispielsweise sollte tryReadInteger keine Ausnahme auslösen, wenn eine saubere Bedingung für das Dateiende auftritt (wenn der Anrufer dies nicht erwartet hätte, hätte der Anrufer readInteger verwendet). Andererseits sollte es wahrscheinlich eine Ausnahme auslösen, wenn die Daten nicht gelesen werden konnten, weil z. Der Memory Stick, der ihn enthielt, wurde herausgezogen. Während solche Ereignisse immer als eine Möglichkeit erkannt werden sollten, ist es unwahrscheinlich, dass der Code für den sofortigen Aufruf bereit ist, irgendetwas Nützliches als Antwort zu tun. Es sollte auf keinen Fall auf die gleiche Weise gemeldet werden, wie dies bei einem Dateiende der Fall wäre.

2
supercat

Das Wichtigste beim Schreiben von Software ist, sie lesbar zu machen. Alle anderen Überlegungen sind zweitrangig, einschließlich der Effizienzsteigerung und der Richtigkeit. Wenn es lesbar ist, kann der Rest bei der Wartung erledigt werden. Wenn es nicht lesbar ist, ist es besser, es einfach wegzuwerfen. Daher sollten Sie Ausnahmen auslösen, wenn dies die Lesbarkeit verbessert.

Denken Sie beim Schreiben eines Algorithmus nur an die Person, die ihn in Zukunft lesen wird. Wenn Sie an einen Ort kommen, an dem ein potenzielles Problem auftreten könnte, fragen Sie sich, ob der Leser sehen möchte, wie Sie jetzt mit diesem Problem umgehen , oder ob das Leser lieber einfach mit dem Algorithmus weitermachen?

Ich denke gerne an ein Rezept für Schokoladenkuchen. Wenn Sie aufgefordert werden, die Eier hinzuzufügen, haben Sie die Wahl: Sie können entweder davon ausgehen, dass Sie Eier haben und mit dem Rezept fortfahren, oder es kann eine Erklärung dafür beginnen, wie Sie Eier erhalten können, wenn Sie keine Eier haben. Es könnte ein ganzes Buch mit Techniken für die Jagd auf wilde Hühner füllen, die Ihnen helfen, einen Kuchen zu backen. Das ist gut, aber die meisten Leute werden dieses Rezept nicht lesen wollen. Die meisten Leute würden es vorziehen, einfach anzunehmen, dass Eier verfügbar sind, und mit dem Rezept fortzufahren. Das ist ein Urteil, das Autoren beim Schreiben von Rezepten treffen müssen.

Es kann keine garantierten Regeln dafür geben, was eine gute Ausnahme ausmacht und welche Probleme sofort behoben werden sollten, da Sie die Gedanken Ihres Lesers lesen müssen. Das Beste, was Sie jemals tun werden, sind Faustregeln, und "Ausnahmen gelten nur für außergewöhnliche Umstände" ist ziemlich gut. Wenn ein Leser Ihre Methode liest, sucht er normalerweise in 99% der Fälle nach der Funktionsweise der Methode, und es wäre ihm lieber, wenn er nicht mit bizarren Eckfällen wie dem Umgang mit Benutzern, die illegale Eingaben eingeben, und anderen Dingen, die so gut wie nie passieren, überfüllt wäre. Sie möchten den normalen Ablauf Ihrer Software direkt sehen, eine Anweisung nach der anderen, als ob niemals Probleme auftreten würden. Das Verständnis Ihres Programms wird schwierig genug sein, ohne sich ständig mit Tangenten auseinandersetzen zu müssen, um jedes kleine Problem zu lösen, das auftreten könnte.

2
Geo