Frage

Ich bin fest entscheiden, wie Ausnahmen in meiner Anwendung zu behandeln.

Viel, wenn meine Probleme mit Ausnahmen von 1) kommen von Daten über einen Remote-Service oder 2) Deserialisieren ein JSON-Objekt zugreifen. Leider kann ich nicht den Erfolg garantiert für eine dieser beiden Aufgaben (cut-Netzwerkverbindung, malformed JSON-Objekt, das aus meiner Kontrolle ist).

Als Ergebnis, wenn ich eine Ausnahme machen begegnen ertappe ich es einfach in der Funktion und FALSE zurück an den Anrufer. Meine Logik ist, dass alle Anrufer wirklich kümmert sich um ist, wenn die Aufgabe erfolgreich war, nicht, warum es war nicht erfolgreich ist.

Hier einige Beispiel-Code (in JAVA) einer typischen Methode)

public boolean doSomething(Object p_somthingToDoOn)
{
    boolean result = false;

    try{
        // if dirty object then clean
        doactualStuffOnObject(p_jsonObject);

        //assume success (no exception thrown)
        result = true;
    }
    catch(Exception Ex)
    {
        //don't care about exceptions
        Ex.printStackTrace();
    }
    return result;
}

Ich denke, dieser Ansatz ist in Ordnung, aber ich bin wirklich neugierig zu wissen, was die besten Praktiken sind für Ausnahmen verwalten (soll ich wirklich Blase eine Ausnahme des ganzen Weg eines Call-Stack nach oben?).

In Zusammenfassung der wichtigsten Fragen:

  1. Ist es in Ordnung, nur Ausnahmen zu fangen, aber nicht Blasen sie nach oben oder formell dem System (entweder über ein Protokoll oder eine Benachrichtigung an den Benutzer) Anmeldern?
  2. Welche bewährten Vorgehensweisen gibt es Ausnahmen, die in allem, was zur Folge haben keinen try / catch-Block erforderlich ist?

Follow Up / Bearbeiten

Vielen Dank für das Feedback, fanden einige ausgezeichnete Quellen auf Ausnahmemanagement online:

Es scheint, dass Ausnahmemanagement eines dieser Dinge ist, die auf kontextbasierte variieren. Aber am wichtigsten ist, sollte man konsequent sein, wie sie Ausnahmen innerhalb eines Systems zu verwalten.

Darüber hinaus achten Sie auf Code-rot über übermäßige try / Fänge oder keine Ausnahme seine Achtung geben (eine Ausnahme das System warnt, was sonst noch gewarnt werden muss?).

Auch das ist eine hübsche Wahl Kommentar von m3rLinEz .

  

neige ich dazu, mit Anders Hejlsberg zu vereinbaren und Sie, dass die meisten Anrufer nur   egal, wenn Operation erfolgreich ist oder nicht.

Von diesem Kommentar bringt es einige Fragen auf, darüber nachzudenken, wenn sie mit Ausnahmen zu tun:

  • Was der Punkt ist, diese Ausnahme ausgelöst wird?
  • Wie macht es Sinn, sie zu behandeln?
  • Hat der Anrufer wirklich über die Ausnahme kümmern oder tun sie kümmern sich nur, wenn der Anruf erfolgreich war?
  • zwingt einen Anrufer eine mögliche Ausnahme graziös zu verwalten?
  • Sind Sie auf die idoms der Sprache respektvoll zu sein?
    • Haben Sie wirklich brauchen eine Erfolgsflag wie boolean zurück? Wiederkehrende boolean (oder ein int) ist eher eine C Mentalität als ein Java (in Java würden Sie nur die Ausnahme behandeln) ein.
    • Folgen Sie den Fehlermanagement-Konstrukte mit der Sprache :) zugeordnet!
War es hilfreich?

Lösung

Es scheint mir seltsam, dass Sie Ausnahmen fangen wollen und sie in Fehlercodes. Warum denken Sie, der Anrufer würde Fehlercodes über Ausnahmen bevorzugen, wenn diesen der Standard sowohl in Java und C # ist?

Wie für Ihre Fragen:

  1. Sie sollten nur Ausnahmen fangen, die Sie tatsächlich verarbeiten kann. Gerade Ausnahmen fangen ist nicht das Richtige in den meisten Fällen zu tun. Es gibt ein paar Ausnahmen (zum Beispiel der Protokollierung und Rangier Ausnahmen zwischen Threads), sondern auch für jene Fälle, sollten Sie in der Regel rethrow die Ausnahmen.
  2. Sie sollten auf jeden Fall nicht viel try / catch-Anweisungen haben in Ihrem Code. Auch hier ist die Idee nur Ausnahmen fangen Sie behandeln können. Sie können einen obersten Exception-Handler umfassen alle nicht behandeln drehen Ausnahmen in etwas ein wenig nützlich für den Endverbraucher, aber andernfalls sollten Sie nicht jede einzelne Ausnahme zu fangen versuchen, in jeder mögliche Platz.

Andere Tipps

Dies ist abhängig von der Anwendung und der Situation. Wenn Ihre Bibliothek Komponente bauen, sollten Sie Ausnahmen sprudeln, obwohl sie sollten mit Ihrer Komponente seinen kontextuellen gewickelt werden. Zum Beispiel, wenn Ihr den Aufbau einer XML-Datenbank und lassen Sie uns sagen, dass Sie das Dateisystem verwenden, um Ihre Daten zu speichern, und Sie verwenden Berechtigungen Dateisystem die Daten zu sichern. Sie würden nicht zu sprudeln eine FileIOAccessDenied Ausnahme wollen als dass Ihre Implementierung Lecks. Stattdessen würden Sie die Ausnahme wickeln und einen AccessDenied Fehler werfen. Dies gilt insbesondere, wenn Sie die Komponente an Dritte verteilen.

Was, wenn es in Ordnung Ausnahmen zu schlucken. Das hängt von Ihrem System. Wenn Ihre Anwendung kann die Fehlerfälle behandeln und es gibt keinen Nutzen aus Benachrichtigung des Benutzers, warum es dann weiter gehen failed, obwohl ich sehr, dass Ihre Log empfehlen das Scheitern. Ich habe immer gefunden, es frustating aufgerufen wird, um ein Problem zu beheben und finden sie die Ausnahme waren beim Schlucken (oder ihn zu ersetzen und einen neuen Wurf statt, ohne dass die innere Ausnahme Einstellung).

Generell verwende ich die folgenden Regeln:

  1. In meinen Komponenten & Bibliotheken ich nur eine Ausnahme fangen, wenn ich es zu behandeln beabsichtige oder etwas zu tun, auf sie basiert. Oder wenn ich zusätzliche Kontextinformationen in Ausnahmefällen zur Verfügung stellen möchten.
  2. Ich benutze einen allgemeinen Versuch fängt bei der Anwendung Einstiegspunkt oder das höchste Niveau möglich. Wenn eine Ausnahme hier bekomme ich log es einfach und lassen Sie es nicht können. Im Idealfall sollten Ausnahmen nie hier.

Ich finde den folgenden Code ein Geruch zu sein:

try
{
    //do something
}
catch(Exception)
{
   throw;
}

Code wie folgt dient keinem Punkt und nicht aufgenommen werden sollten.

Ich möchte eine andere gute Quelle zum Thema empfehlen. Es ist ein Interview mit Erfindern von C # und Java, Anders Hejlsberg und James Gosling jeweils zum Thema Java Checked Exception.

Ausfall und Ausnahmen

Es gibt auch große Ressourcen am unteren Rand der Seite.

Ich neige dazu, mit Anders Hejlsberg zu vereinbaren und Sie, dass die meisten Anrufer kümmern sich nur, wenn der Betrieb erfolgreich ist oder nicht.

  

Bill Venners : Sie erwähnt   Skalierbarkeit und Versionierung Bedenken   in Bezug auf geprüfte Ausnahmen.   Könnten Sie erklären, was von Ihnen bedeuten   diese beiden Fragen?

     

Anders Hejlsberg : Lassen Sie uns beginnen mit   Versionierung, weil die Anliegen   ziemlich einfach dort zu sehen. Sagen wir, ich   eine Methode foo erstellen, die es erklärt   werfen Ausnahmen A, B und C. In   Version zwei von foo, ich möchte hinzufügen   Bündel von Features, und jetzt foo könnten   werfen Ausnahme D. Es ist ein Bruch   ändern für mich D hinzufügen, um die Würfe   Klausel dieser Methode, weil   bestehenden Anrufer dieser Methode wird   fast sicher handhaben nicht, dass   Ausnahme.

     

Hinzufügen einer neuen Ausnahme ein wirft   Klausel in einer neuen Version bricht Client   Code. Es ist wie eine Methode eine Zugabe   Schnittstelle. Nachdem Sie ein veröffentlichen   Schnittstelle, ist es für alle praktischen   Zwecke unveränderlich, weil jeder   Umsetzung könnte es haben die   Methoden, die Sie in der hinzufügen möchten   nächste Version. Also du hast erstellen   eine neue Schnittstelle statt. Ähnlich   mit Ausnahmen, würden Sie entweder   eine ganz neue Methode erstellen aufgerufen   foo2, die mehr Ausnahmen auslöst, oder   Sie müßten Ausnahme D fangen in   die neuen foo, und verwandeln die D in   ein A, B oder C.

     

Bill Venners : Aber sind Sie nicht brechen   ihr Code in diesem Fall trotzdem, auch   ohne in einer Sprache geprüft   Ausnahmen? Wenn die neue Version von foo   wird eine neue Ausnahme werfen, dass   Kunden sollten darüber nachdenken, Handhabung,   ihr Code nicht gebrochen nur durch die   Tatsache, dass sie nicht erwarten, dass   Ausnahme, wenn sie schreibt den Code?

     

Anders Hejlsberg : Nein, denn in vielen   der Fälle ist es egal Menschen. Sie sind   nicht davon gehen zu handhaben   Ausnahmen. Es gibt eine untere Ebene   Exception-Handler um ihre Botschaft   Schleife. Das Handler wird nur zu   bringt einen Dialog, der sagt, was ging   falsch und fortzusetzen. die Programmierer   ihren Code schützen, indem sie versuchen zu schreiben   schließlich ist überall, so dass sie kommen wieder   out korrekt, wenn eine Ausnahme auftritt,   aber sie sind nicht wirklich daran interessiert,   die Behandlung von Ausnahmen.

     

Die throws-Klausel, zumindest den Weg   es ist in Java implementiert, nicht   Sie zwingen, unbedingt zu handhaben die   Ausnahmen, aber wenn Sie behandeln nicht   sie, es zwingt Sie zu bestätigen,   genau die Ausnahmen passieren könnte   durch. Es erfordert, dass Sie entweder   fangen erklärt Ausnahmen oder sie setzen   in Ihrem eigenen throws-Klausel. Arbeiten   Um dieses Erfordernis, die Menschen tun   lächerliche Dinge. Zum Beispiel, sie   dekorieren jede Methode mit „wirft   Ausnahme.“Das gerade komplett   besiegt die Funktion, und Sie gerade gemacht   der Programmierer schreiben mehr gobbledy   gunk. Das bedeutet nicht, jemand helfen.

EDIT: Hinzugefügt mehr Details über die converstaion

Checked Ausnahmen sind ein umstrittenes Thema im Allgemeinen und in Java insbesondere (später werde ich versuchen, einige Beispiele für die Befürworter zu finden und im Gegensatz zu ihnen).

Als Faustregeln, die Ausnahmebehandlung etwas um diese Richtlinien sein sollten, in keiner bestimmten Reihenfolge:

  • Aus Gründen der Wartbarkeit, immer Ausnahmen melden Sie sich so, dass, wenn Sie Fehler sehen beginnen, wird das Protokoll in unterstützen Sie an den Ort Ihrer Bug zeigt hat wahrscheinlich gestartet. Lassen Sie niemals printStackTrace() oder Leute wie sie, die Chancen einer Ihrer Nutzer sind, wird einer dieser Stack-Traces schließlich bekommen, und haben genau Null Wissen , was damit zu tun.
  • Fang Ausnahmen können Sie umgehen, und nur diejenigen, und mit ihnen umgehen , nicht nur sie den Stapel nicht erbrechen.
  • Sie immer eine bestimmte Ausnahmeklasse fangen, und in der Regel sollten Sie nie Art Exception fangen, sind Sie sehr wahrscheinlich sonst wichtige Ausnahmen schlucken.
  • Nie (je) fangen Errors !! , das heißt: Nie Throwables fangen als Errors Subklassen der letzteren sind. Errors sind Probleme, die Sie höchstwahrscheinlich nie (z OutOfMemory oder andere JVM Ausgaben)
  • zu handhaben können,

Ihre speziellen Fall betrifft, so stellen Sie sicher, dass jeder Kunde Ihre Methode aufrufen wird die richtige Rückgabewert erhalten. Wenn etwas fehlschlägt, ein boolean-Verfahren zum Zurückkehren könnte false zurück, aber stellen Sie sicher, dass die Orte, die Sie, dass die Methode in der Lage sind, rufen Sie an, dass zu behandeln.

Sie sollten nur die Ausnahmen fangen Sie mit umgehen können. Zum Beispiel, es zu tun, wenn Sie mit dem Lesen über ein Netzwerk und die Verbindungszeiten und Sie erhalten eine Ausnahme Sie es erneut versuchen können. Allerdings, wenn Sie ein Netzwerk zu lesen über sind und eine IndexOutOfBounds Ausnahme erhalten, kann man wirklich nicht umgehen, weil Sie nicht (gut, in diesem Fall werden Sie nicht) wissen, was sie verursacht hat. Wenn Sie vorhaben, falsche oder -1 oder null zurück, stellen Sie sicher, dass es für bestimmte Ausnahmen. Ich möchte nicht über eine Bibliothek verwende ich eine falsche auf einem Netzwerk zurückkehrt lesen, wenn die ausgelöste Ausnahme ist der Haufen aus Speicher.

Ausnahmen sind Fehler, die nicht Teil der normalen Programmausführung sind. Je nachdem, was Ihr Programm tut und seine Verwendungen (das heißt ein Textverarbeitungsprogramm im Vergleich zu einem Herzmonitor) Sie wollen verschiedene Dinge tun, wenn Sie eine Ausnahme zu begegnen. Ich habe mit dem Code gearbeitet, die Ausnahmen als Teil der normalen Ausführung verwendet, und es ist auf jeden Fall ein Code Geruch.

Bsp.

try
{
   sendMessage();

   if(message == success)
   {
       doStuff();
   }
   else if(message == failed)
   {
       throw;
   }
}
catch(Exception)
{
    logAndRecover();
}

Dieser Code macht mich barf. IMO sollten Sie nicht von Ausnahmen, wenn sein ein kritisches Programm wiederherzustellen. Wenn Ihr Wurf Ausnahmen dann schlechte Dinge geschehen.

All das scheint über vernünftig, und oft Ihr Arbeitsplatz eine Politik haben kann. Bei uns uns Arten von Exception definiert haben: SystemException (ungeprüft) und ApplicationException (markiert).

Wir haben vereinbart, dass SystemExceptions unwahrscheinlich sein erstattungsfähig und wird bve einmal oben behandelt. Zur weiteren Zusammenhang werden unsere SystemExceptions exteneded um anzuzeigen, wo sie aufgetreten sind, beispielsweise RepositoryException, ServiceEception, etc.

ApplicationExceptions könnte betriebswirtschaftliche Bedeutung wie InsufficientFundsException haben und sollte von Client-Code behandelt werden.

Witohut ein konkretes Beispiel, dann ist es schwierig, sich auf Ihre Implementierung zu kommentieren, aber ich würde nie Return-Codes verwenden, sie sind ein Wartungsproblem. Sie könnten eine Ausnahme schlucken, aber Sie müssen deshalb, um zu entscheiden, und immer das Ereignis und stacktrace anmelden. Schließlich ist, wie Ihre Methode keine andere hat die Verarbeitung ist es ziemlich redundant (außer für die Verkapselung?), So doactualStuffOnObject(p_jsonObject); eine boolean zurückgeben kann!

Nach einigem Nachdenken und Blick auf Ihrem Code scheint es mir, dass Sie einfach nur Erneutes Auslösen die Ausnahme als boolean. Sie könnten nur die Methode lassen diese Ausnahme durchlaufen (Sie müssen nicht einmal, es zu fangen haben) und damit in dem Anrufer zu beschäftigen, da dies der Ort ist, wo es darauf ankommt. Wenn die Ausnahme der Anrufer verursachen diese Funktion zu wiederholen, sollte der Anrufer die sein, die Ausnahme zu kontrollieren.

Es kann manchmal vorkommen, dass die Ausnahme Ihr keinen Sinn für den Anrufer machen begegnen (das heißt, es ist ein Netzwerk Ausnahme), in dem Fall, dass Sie es in einer domänenspezifischen Ausnahme wickeln sollten.

Wenn auf der anderen Seite, die Ausnahme signalisiert einen nicht behebbaren Fehler in Ihrem Programm (dh die möglichen Folge dieser Ausnahme wird zum Programmende sein) Ich mag persönlich, dass explizit machen, indem sie zu kontrollieren und eine Laufzeitausnahme zu werfen.

Wenn Sie vorhaben, das Codemuster in Ihrem Beispiel zu verwenden, rufen Sie es TryDoSomething, und nur bestimmte Ausnahmen zu fangen.

Auch Sehen Sie eine Ausnahme Filter , wenn Ausnahmen für diagnostische Zwecke anzumelden. VB hat Sprachunterstützung für Exception-Filter. Der Link zu Greggm Blog hat eine Implementierung, die von C # verwendet werden kann. Ausnahmefilter haben bessere Eigenschaften für debuggability über Fang und rethrow. Insbesondere können Sie das Problem in dem Filter anmelden und lassen die Ausnahme propagieren fortzusetzen. Diese Methode ermöglicht eine ein JIT Anbringen (Just in Time) Debugger den vollständigen Originalstapel zu haben. Ein rethrow schneidet den Stapel an dem Punkt, ab es erneut ausgelöst wurde.

Die Fälle, in denen TryXXXX Sinn macht, wenn Sie einen Dritten Funktion Verpackung, die in Fällen wirft die nicht wirklich außergewöhnlich sind, oder sind einfach schwer zu testen, ohne die Funktion aufrufen. Ein Beispiel dafür wäre, wie etwas sein:

// throws NumberNotHexidecimalException
int ParseHexidecimal(string numberToParse); 

bool TryParseHexidecimal(string numberToParse, out int parsedInt)
{
     try
     {
         parsedInt = ParseHexidecimal(numberToParse);
         return true;
     }
     catch(NumberNotHexidecimalException ex)
     {
         parsedInt = 0;
         return false;
     }
     catch(Exception ex)
     {
         // Implement the error policy for unexpected exceptions:
         // log a callstack, assert if a debugger is attached etc.
         LogRetailAssert(ex);
         // rethrow the exception
         // The downside is that a JIT debugger will have the next
         // line as the place that threw the exception, rather than
         // the original location further down the stack.
         throw;
         // A better practice is to use an exception filter here.
         // see the link to Exception Filter Inject above
         // http://code.msdn.microsoft.com/ExceptionFilterInjct
     }
}

Ob Sie ein Muster wie TryXXX verwenden oder nicht, ist eher eine Art Frage. Die Frage, alle Ausnahmen zu kontrollieren und sie beim Schlucken ist kein Stil Thema. Stellen Sie sicher, unerwartete Ausnahmen sind erlaubt zu propagieren!

Ich schlage vor, Ihre Hinweise aus der Standardbibliothek für die Sprache nehmen Sie verwenden. Ich kann nicht für C # sprechen, aber sie auf Java aus.

Zum Beispiel java.lang.reflect.Array hat eine statische set Methode:

static void set(Object array, int index, Object value);

Der C Weg wäre,

static int set(Object array, int index, Object value);

... mit dem Rückgabewert ein Erfolgsindikator ist. Aber du bist nicht in C-Welt nicht mehr.

Wenn Sie Ausnahmen umarmen, sollten Sie feststellen, dass es Ihren Code einfacher und klarer macht, indem Sie Ihren Fehlerbehandlungscode weg von Ihrer Kernlogik zu bewegen. Richten Sie haben viele Anweisungen in einem einzigen try Block.

Wie andere bereits erwähnt haben - sollten Sie so spezifisch wie möglich sein, in der Art der Ausnahme, die Sie fangen.

Wenn Sie vorhaben, eine Ausnahme zu fangen und return false, sollte es eine sehr spezifische Ausnahme sein. Sie tun das nicht, sind Sie alle von ihnen zu kontrollieren und die Rückkehr falsch. Wenn ich einen MyCarIsOnFireException bekommen möchte ich sofort darüber Bescheid wissen! Der Rest der Ausnahmen könnte ich nicht kümmern uns um. So sollten Sie einen Stapel von Exception-Handler, die „whoa whoa etwas falsch hier“ für einige Ausnahmen sagen (rethrow oder fangen und erneut auslösen eine neue Ausnahme, die besser erklärt, was passiert ist) und nur return false für andere.

Wenn dies ein Produkt, das Sie Sie sollten diese Ausnahmen werden den Markt bringen werde irgendwo anmelden, wird es Ihnen tune Dinge helfen, in die Zukunft.

Edit: Was die Frage von allem in einem try / catch Einwickeln, ich denke, die Antwort ist ja. Ausnahmen sollten in Ihrem Code so selten sein, dass der Code im catch-Block so selten führt, dass es überhaupt nicht getroffen hat Leistung. Eine Ausnahme sollte ein Zustand, wo Ihre Zustandsmaschine brach und nicht weiß, was zu tun ist. Mindestens rethrow eine Ausnahme, die erklärt, was zu der Zeit geschieht, und hat die abgefangene Ausnahme im Innern. „Exception in Verfahren doSomeStuff ()“ ist nicht sehr hilfreich für alle, die, um herauszufinden, haben, warum es brach, während Sie im Urlaub (oder bei einem neuen Job) sind.

Meine Strategie:

Wenn die ursprüngliche Funktion zurück void ich Bool zurückzukehren ändern. Wenn Ausnahme / Fehler zurückgeben false , wenn alles in Ordnung ist Rückkehr true .

Wenn die Funktion sollte etwas dann zurück, wenn Ausnahme / Fehler zurück aufgetreten null , da sonst der Mehrweg-Artikel.

Anstelle von Bool a string zurückgegeben werden, um die Beschreibung des Fehlers enthält.

In jedem Fall, bevor irgendetwas anmelden, um den Fehler zurück.

Einige ausgezeichnete Antworten hier. Ich möchte hinzufügen, dass, wenn Sie am Ende mit etwas zu tun, wie Sie auf dem Laufenden, zumindest mehr als die Stack-Trace drucken. Sagen Sie, was Sie zu der Zeit taten, und Ex.getMessage (), dem Entwickler eine Chance zu geben.

try / catch-Blöcke bilden einen zweiten Satz von Logik über den ersten (Haupt-) Satz eingebettet ist, als solche sind sie eine gute Möglichkeit, aus unlesbar zu hämmern, schwer zu debuggen Spaghetti-Code.

Dennoch verwendet vernünftigerweise sie Wunder in Lesbarkeit arbeiten, aber Sie sollten nur zwei einfache Regeln befolgen:

  • verwenden sie (sparsam) auf der Low-Level-Bibliothek Probleme mit der Handhabung zu fangen, und streamen sie zurück in das Haupt logischen Fluss. Die meisten der Fehlerbehandlung wir wollen, sollten aus dem Code kommen selbst, als Teil der Daten selbst. Warum besondere Bedingungen abhängig machen, wenn die zurückgegebenen Daten nicht besonders?

  • Verwenden Sie einen großen Handler auf der höheren Ebene oder alle der seltsamen Bedingungen zu verwalten im Code entstehen, die nicht auf einem niedriges Niveau gefangen werden. Haben etwas Nützliches mit den Fehlern (Scheitholz, neu gestartet wird, Einziehungen, etc).

Anders als diese beiden Arten von Fehlerbehandlung, die alle den Rest des Codes in der Mitte sollte frei von try / catch-Code und Fehlerobjekte sein. Auf diese Weise funktioniert es einfach und so egal zu erwarten, wo Sie es verwenden, oder das, was Sie damit machen.

Paul.

kann ich ein wenig spät mit der Antwort, aber die Fehlerbehandlung ist etwas, das wir immer ändern kann und entlang der Zeit weiterentwickeln. Wenn Sie etwas mehr über dieses Thema lesen möchten, schrieb ich einen Beitrag in meinem neuen Blog darüber. http://taoofdevelopment.wordpress.com

Happy-Codierung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top